2012-02-11 34 views
3

我在下面有一個特定的場景。下面的代碼應該打印B和C類的'say()'函數並打印'B說..'和'C說...'但它不會。任何想法..我正在學習多態,所以也有在下面的代碼行中評論了與它相關的幾個問題。多態對象列表

class A 
{ 
public: 
// A() {} 
    virtual void say() { std::cout << "Said IT ! " << std::endl; } 
    virtual ~A(); //why virtual destructor ? 
}; 

void methodCall() // does it matters if the inherited class from A is in this method 
{ 
    class B : public A{ 
    public: 
     // virtual ~B(); //significance of virtual destructor in 'child' class 
     virtual void say() { // does the overrided method also has to be have the keyword 'virtual' 
      cout << "B Sayssss.... " << endl; 
     } 
    }; 
    class C : public A { 
    public: 
     //virtual ~C(); 
     virtual void say() { cout << "C Says " << endl; } 
    }; 

    list<A> listOfAs; 
    list<A>::iterator it; 

    # 1st scenario 
    B bObj; 
    C cObj; 
    A *aB = &bObj; 
    A *aC = &cObj; 

    # 2nd scenario 
    // A aA; 
    // B *Ba = &aA; 
    // C *Ca = &aA; // I am declaring the objects as in 1st scenario but how about 2nd scenario, is this suppose to work too? 

    listOfAs.insert(it,*aB); 
    listOfAs.insert(it,*aC); 

    for (it=listOfAs.begin(); it!=listOfAs.end(); it++) 
    { 
     cout << *it.say() << endl; 
    } 
} 

int main() 
{ 
    methodCall(); 
    return 0; 
} 

回答

2

你的問題被稱爲切片,你應該檢查這個問題:Learning C++: polymorphism and slicing

你應該聲明此列表的指針的列表A S:

list<A*> listOfAs; 

,然後插入這些aBaC指向它的指針,而不是創建它們指向的對象的副本。你插入元素列表的方式是錯的,你倒是應該使用push_back功能插入:

B bObj; 
C cObj; 
A *aB = &bObj; 
A *aC = &cObj; 

listOfAs.push_back(aB); 
listOfAs.push_back(aC); 

然後你的循環可能看起來像這樣:

list<A*>::iterator it; 
for (it = listOfAs.begin(); it != listOfAs.end(); it++) 
{ 
    (*it)->say(); 
} 

輸出:

B Sayssss.... 
C Says 

希望這可以幫助。

+0

其實*使用*一個裸指針的容器是一個潘多拉的黃蜂巢,但任何數量的東西都可能出錯... – 2012-02-11 16:32:30

+0

我同意。但在這種情況下,我認爲使用裸指針更合適,以便他更好地理解到底發生了什麼。 – LihO 2012-02-11 16:36:08

+0

在上面的情況下,我不得不照顧列表中的元素,一旦我用它..我必須刪除它或什麼? – LivingThing 2012-02-15 18:52:16

1

多態性虛擬類層次的只能通過引用指針到基子:

struct Der : Base { /* ... */ }; 

Der x; 

Base & a = x; 

a.foo(); // calls Der::foo() from x 

功能foo是多態的調度,如果它是在Base一個虛函數;多態性是指這樣一個事實,即當您調用Base類型的對象的成員函數時,實際調用的函數可以在類Der中實現。

容器只能存儲固定類型的元素。爲了存儲一個多態的集合,你可以擁有一個指向基類的指針的容器。既然你需要存儲的實際對象的其他地方,生命週期管理是不平凡的,最好的留給專用包裝如unique_ptr

#include <list> 
#include <memory> 


int main() 
{ 
    std::list<std::unique_ptr<Base>> mylist; 

    mylist.emplace_back(new Der1); 
    mylist.emplace_back(new Der2); 
    // ... 

    for (p : mylist) { p->foo(); /* dispatched dynamically */ } 
} 
+0

1:這是什麼「容器只能存儲固定類型的元素」。意味着?? 2:「你可以改爲容器指向基類」 你的意思是'列表 listOfAs'而不是'列表 listOfAs;' – LivingThing 2012-02-15 19:01:46

0

list::iterator it; B bObj; C cObj; A *aB = &bObj; A *aC = &cObj; listOfAs.insert(it,*aB);

你不需要初始化 「它」? 我相信你應該這樣做= listOfAs.begin();在開始插入之前。