2009-01-28 70 views
2

是否總是需要從堆中分配內存以促進動態多態?到目前爲止我所遇到的所有例子都指向相同的。 動態內存分配通常可以在實時編程中避免。因此,如下面的代碼所示,使用動態多態的堆棧有什麼缺點。動態多態和動態內存分配

class Base 
{ 
    public: 
     virtual void Display()= 0; 
}; 

class Derived:public Base 
{ 
    public: 
     void Display() 
     { 
      cout << "In derived" << endl; 
     } 
}; 

int main() 
{ 
    Base* base; 
    Derived derived1; 

    base = &derived1; 
    base->Foo();  
    return 0; 
} 

回答

7

一個更好的例子是:

void func(Base &base); 

int main() 
{ 
    Derived derived; 

    func(derived); 

    return 0; 
} 

使用多態性不必是在棧上創建對象附近。

很多我們的單元測試代碼,這些天看起來大致是:

void test() 
{ 
    MockObject mockObj; 
    RealObject objectToBeTested(mockObj); 

    // Do tests 
} 

這密切依賴於多態性,但在棧上創建對象。

0

我覺得這很好。唯一可能的缺點是在堆棧上創建的對象範圍有限,但這不一定與多態相關。

0

使用堆棧沒有問題。

當你正在使用的堆棧,那麼你往往確切地知道它是什麼類型的對象......所以沒有必要的方法是虛擬的,它是無害的,但不必要的,例如:

Derived derived; 
derived.Foo(); 

然而,對象(它存在在棧上)可以被傳遞到其接受一個超類實例作爲一個參數的子程序(在這種情況下,事實上,它是一個子類有用/使用):

void foo(Base* base) 
{ 
    ... 
} 

void test() 
{ 
    Derived derived; 
    foo(&derived); 
} 
0

使用對於你展示的簡單案例,堆棧將會很好。動態多態vs靜態的一個實時問題是增加時間去經歷方法調用的間接。每個方法調用哪個是額外的內存訪問。

您需要解釋更多關於您如何分析其他因素的操作,例如,是保證在物理內存中的堆棧框架,共享,實例數量,實例的壽命

4

如果您想使用多態性,您不要如您在問題中指出的那樣使用堆。但你經常沒有別的選擇。小人爲的例子:

void doSomething(int what) { 
    // figure out which implementation to create 
    Base * b; 
    if(doA) { 
     b = new ConcreteA; // 1a 
    } else if(doB) { 
     b = new ConcreteB; // 1b 
    } 
    ... 
    b->...; // 2 
} 

不能使用堆棧,因爲在那一刻,你知道該怎麼做,1a和1b,每次你從堆棧獲得存儲將被回收時範圍又離開了。你必須使用這個堆,因爲你需要一些能夠保存本地作用域的存儲。

一些圖書館宣稱他們能夠不使用堆,但仍表現爲多態。他們通常做,投放新:

void doSomething(int what) { 
    // allocate form *the stack*, outside the if blocks, so this 
    // storage lasts until the function returns 
    char buffer[MAX(sizeof (ConcreteA), sizeof(ConcreteB))]; 
    if(doA) { 
     new (buffer) ConcreteA; // 1a 
    } else if(doB) { 
     new (buffer) ConcreteB; // 1b 
    } 
    Base *b = static_cast<Base*>(static_cast<void*>(buffer)); 
    b->...; // 2 
} 

在1A和1B的新的呼叫現在使用的堆棧作爲存儲爲創建的對象上創建的緩衝區。所以,不再需要堆內存分配。這種分配形式的主要缺點是,C++目前無法判斷緩衝區是否正確對齊類型ConcreteA和ConcreteB。所以,可能是數組在2字節邊界上對齊,但需要在4字節邊界上創建對象,導致在您嘗試將這些對象創建到該緩衝區時出現未定義的行爲。

Boost.Function是使用這種放置新方法創建多態類型對象而不使用使用小緩衝區的堆分配(因此,它的作用稱爲小緩衝區優化)的庫之一。