2016-11-06 20 views
1

以下內容與this直接相關。我希望能夠一次只能調用一個類,以節省內存,但也因爲我打算在後面添加一個GUI,所以我可以通過一個類來調用這些類下拉菜單(例如)。一次只實例化一個類,出一組類,節省內存

我試圖使組成,這是哪冒出來的:

#include <iostream> 

class Power 
{ 
private: 
    double m_x; 
public: 
    Power() {std::cout<<"Power\n";} 
    Power(double x): m_x {x} {std::cout<<"Power("<<x<<")\n";} 
    ~Power() {std::cout<<"~Power\n";} 
    const double getX() const { return m_x; } 
}; 

class Scanner 
{ 
private: 
    Power m_power; 
public: 
    Scanner() {std::cout<<"Scanner\n";} 
    Scanner(const Power &p): m_power {p} {std::cout<<"Scanner("<<&p<<")\n";} 
    void print() {std::cout<<"x="<<m_power.getX()<<'\n';} 
}; 

class Printer 
{ 
private: 
    Power m_power; 
public: 
    Printer() {std::cout<<"Printer\n";} 
    Printer(const Power &p): m_power {p} {std::cout<<"Printer("<<&p<<")\n";} 
    void print() {std::cout<<"x="<<m_power.getX()<<'\n';} 
}; 

class Copier // if Copier is to be used for "unification", will "public" be needed? 
{ 
private: 
    Scanner *m_s; 
    Printer *m_p; 
    int m_i; 
public: 
    Copier() {std::cout<<"Copier\n";} 
    Copier(const Power &p, int i): m_i {i} 
    { 
     if (i) 
      m_s = new Scanner(p); 
     else 
      m_p = new Printer(p); 
     std::cout<<"Copier("<<&p<<","<<i<<")\n"; 
    } 
    void print() { std::cout << (m_i ? m_s->getX() : m_p->getX()) << '\n'; } 
}; 

int main(int argc, char *argv[]) 
{ 
    Scanner *s {new Scanner(Power(2.3))}; 
    s->print(); 
    Printer *p {new Printer(Power(3.14))}; 
    p->print(); 
    s->print(); // here, both *s and *p exist, both use memory 
    // this comes after considering adding class Copier 
    Copier *c {new Copier(Power(1.618), 0)}; 
    c->print(); 
    c = new Copier(Power(2.718), 1); 
    c->print(); 
    return 0; 
} 

忽略Copier了一下。正因爲如此,我可以使用它,這是什麼出來:

Power(2.3) 
Scanner(0x7ffc80d98c10) 
~Power 
x=2.3 
Power(3.14) 
Printer(0x7ffc80d98c20) 
~Power 
x=3.14 
x=2.3 

現在的(大)的問題是,有在內存中的多個對象,有*s並有*p,你可以看到x能pe用3.142.3打印出來。如果我有兩門以上的課程(我可以),我可以打電話給每個班級,每個班級都會佔用記憶。這不是我想要的。

如何一次只能調用一個類而不必調用額外的重置或刪除?我想爲它增加一個班級,請參閱Copier。但我不能使用std::unique_ptr,代碼中的解決方案不僅非常難看,而且甚至不起作用。另外它調用構造函數就像瘋了一樣。

我想在一個簡單的函數使用std::unique_ptr,與std::make_unique(需要c++14,我寧願保留一些較大的安全邊際,但我也能忍受它,太)。它也不會工作,因爲它指向Power(如果我叫z->print()它說'class Power' has no member 'print'):

std::unique_ptr<Power> call(const Power &p, const int &i) 
{ 
    if (i) 
     return std::make_unique<Printer>(p); 
    else 
     return std::make_unique<Scanner>(p); 
} 

我不知道如何使這個。總之,類ScannerPrinter,以及存在的任何其他的,都是perfom一個任務專用類,只有在他們的計算方式,並且所有的獨特使Power使用一些常見的變量(除了自己)。我不認爲將公共變量移動到每個類是非常有效的,因爲它們只會膨脹代碼,並且據我瞭解,「如果您可以使用存儲類而不是一遍又一遍地重複相同的變量,用它「(不是我的話,這是真的嗎?)。然後,我希望能夠實例化這些類,但一次只能有一個活動,以節省內存。

作爲一個例子,假設一個類使得1mil的值的陣列,然後另一個使得1mil的不同的值,並依此類推。想象一下,在內存中擁有該數組的次數與實例化的類相同。我不想那樣。 Copier的目的本來是一次只能根據條件調用一個類。任務完成?撥打另一個電話,但忘記以前完成的任何事情,重新開始。而所有這些只能通過一個小部件進行調用,例如從列表中選擇,點擊&去,這將在稍後添加。


這是一個愚蠢的錯誤,我忘記了複製粘貼後刪除public ...。我也試過現在的代碼(與Copier),它編譯,但仍然無法正常工作,m_x保持爲空,即使採用內Copier 2個ScannerPrinter指針作爲成員變量的非常醜陋的解決方案。


好,一些嘗試後,我不能讓我想要的東西,所以我想回到我原來的想法,即使這意味着繼承。所以,我想出了這一段代碼,在那裏我改變了名稱,以使更多的意義(?):

#include <iostream> 

class Garage 
{ 
protected: 
    double m_x; // gas, tires, etc, that all cars use, reside in the Garage 
public: 
    Garage() {std::cout<<"Garage\n";} 
    virtual ~Garage() {std::cout<<"~Garage\n";} 
}; 

class Audi: virtual public Garage 
{ 
public: 
    Audi() {std::cout<<"Audi\n";} 
    void f(const double &x) { m_x=x; std::cout<<"Audi::f("<<x<<")\n";} 
}; 

class Bmw: virtual public Garage 
{ 
public: 
    Bmw() {std::cout<<"Bmw\n";} 
    void f(const double &x) { m_x=x; std::cout<<"Bmw::f("<<x<<")\n";} 
}; 

class Driver: public Audi, public Bmw 
{ 
private: 
    double m_y; // report of driving, based on m_x 
public: 
    Driver() {std::cout<<"Driver\n";} 
    Driver(const double &x, int i) 
    { 
     if (i) 
      Bmw::f(x); 
     else 
      Audi::f(x); 
     m_y = -m_x; 
     std::cout<<"Driver("<<x<<","<<i<<")\n"; 
    } 
    void print() { std::cout << "x=" << m_x << ", y=" << m_y << '\n'; } 
}; 

int main(int argc, char *argv[]) 
{ 
    Driver *d {new Driver(1.618, 0)}; 
    d->print(); 
    d = new Driver(0.618, 1); 
    d->print(); 
    // even iteration works now 
    delete d; 
    d = nullptr; // to be sure it's dead(?) 
    for (int i=0; i<2; ++i) 
    { 
     d = new Driver(3.14, i); 
     d->print(); 
    } 
    return 0; 
} 

現在,這個工作,但我有一種感覺,我設置一個新的記錄上糟糕的代碼例。請不要爲此而打我,而是指出所有的錯誤,或者你會如何去達到同樣的結果。儘管如此,即使它看起來像我想要的那樣工作,它仍然會調用所有分支上的所有構造函數,而不是僅在需要的分支上。我意識到(我的道歉),我忘了說Driver,在這裏,它還負責進一步使用m_x,因爲它的m_y(這就是爲什麼代碼有點不同)。


我想指出的是,我不是固定在保持此代碼,或任何其他的,我願意改變和適應,只要我達到我的目的。但是因爲我是初學者,所以我不能做太多的組合,所以我只剩下提出的結果就是我試圖讓自己理解。上面的程序在運行時給出了我想要的內容,甚至有可能形成一個循環,這會讓我在以後的GUI中更容易使用它。名字,因爲它們是最有意義的作文,Garagehas-aBmw,這就是我的嘗試,但我無法獲得我想要的。因此,即使這種方式使用繼承,但沒有意義,因爲我保留了名稱,以表明我的初步嘗試與組合。發佈此信息的主要原因是爲了顯示我希望程序執行的操作。在main()會發生什麼會在GUI中使用,我正在考慮Qt,因爲我希望這可以在所有3個主要操作系統上運行。因此,有可能一次調用一輛車,使用它,並且能夠存儲以前的信息,而不會在內存中存儲過時的對象,只有m_x * nr_of_cars,將使它更容易處理。

+0

你爲什麼無論從動力派生並有電源會員? – Mat

+3

這個設計仍然充滿了繼承,甚至是多重繼承。它沒有意義,因爲掃描儀和打印機不是電源,它們有能力。如果基類是類似「機器」的東西,那將是有意義的。在開始關注諸如「節省內存」之類的東西之前,你應該開始閱讀一本關於面向對象設計的書。 –

+0

@Mat我使用http://www.learncpp.com/cpp-tutorial/102-composition/作爲參考(請參閱Point2D和Creature的更低版本)。 #ChristianHackl如果我改變電源到車庫,掃描儀和打印機到奧迪和寶馬,複印機到驅動程序,那麼這些在構圖方面會更有意義嗎? –

回答

0

使用一些std::unique_ptr構造:

std::unique_ptr<Power> 
call(const Power &p, const int &i) { 
    if (i) 
    return std::unique_ptr<Power>(new Printer(p)); 
    else 
    return std::unique_ptr<Power>(new Scanner(p)); 
} 

也許你真正想要的是一個tagged union。按照rule of five。請參閱this以獲取靈感。

+0

我在構造函數和外部嘗試過,但是'm_x'仍然是空的。 –

1

這是一種方法。

{ // scope begins 
    Printer p; // note, no pointers 
    p.print(); 
} // scope ends, p is gone 

在這裏,我們有一個對象,出現,做一件事,然後消失。

這裏是另一個

boost::variant<Printer,Scaner,Copier> psc(Printer()); 
psc.get<Printer>().print(); 
psc = Scaner(); // the printer is gone 
+0

爲什麼不'std :: variant'? –

+0

如果我這樣做了,稍後我將如何通過小部件調用這樣的事情? –

+1

@ChristianHackl C++ 17還沒有在這裏。 –