2010-05-13 53 views
3

其实我是C++新手。我尝试了一些东西(实际上是地图容器),但它不会像我认为的那样工作......在发布我的代码之前,我会尽快解释它。需要帮助地图(C++,STL)

我创建了3类:

ClassA的 ClassDerivedA ClassAnotherDerivedA

最后两个那些从 “ClassA的” 导出。

此外我创建的地图:

map<string,ClassA> test_map; 

我把一些对象(从类型ClassDerivedA和ClassAnotherDerivedA)到地图。请记住:映射值来自类型“ClassA”。这只会因为多态性而起作用。最后,我创建了一个遍历我的地图的迭代器,并将用户输入与我在地图中的键进行比较。如果它们匹配,它将调用一个名为“printOutput”的特定方法。

并且存在问题: 尽管我将“printOutput”声明为“虚拟”,但唯一调用的方法是来自我的基类的,但为什么? 这里是代码:

#include <iostream> 
#include <map> 

using namespace std; 

class ClassA 
{ 
    public: 
     virtual void printOutput() { cout << "ClassA" << endl;  } 
}; 

class ClassDerivedA : public ClassA 
{ 
    public: 
     void printOutput() { cout << "ClassDerivedA" << endl;  } 
}; 

class ClassAnotherDerivedA: public ClassA 
{ 
    public: 
     void printOutput() { cout << "ClassAnotherDerivedA" << endl;  } 
}; 

int main() 
{ 
    ClassDerivedA class_derived_a; 
    ClassAnotherDerivedA class_another_a; 


    map<string,ClassA> test_map; 
    test_map.insert(pair<string,ClassA>("deriveda", class_derived_a)); 
    test_map.insert(pair<string,ClassA>("anothera", class_another_a)); 

    string s; 

    while(cin >> s) 
    { 
    if(s != "quit") 
    { 
     map<string,ClassA>::iterator it = test_map.find(s); 
     if(it != test_map.end()) 
     it->second.printOutput(); 
    } 
    else 
     break; 
    } 

} 
+3

作为一个侧面说明,您可以使用make_pair(),而不是对<字符串,ClassA的>(),少写... – 2010-05-13 21:43:54

回答

13

问题在分化。您正在将ClassA值存储在您的地图中。将派生类实例存储到映射中时,get将切片为ClassA对象。你需要在你的地图中存储指针而不是值。

上切片的更多信息请参阅本:What is object slicing?

+0

现在工作!我误解了一些东西:多态(在C++中)只能使用指针(就像Neil Butterworth所说的)。谢谢大家! – 2010-05-14 10:50:04

+0

多态性适用于指针或引用,但不能在容器中使用引用。所以在这种情况下,你必须使用某种类型的指针。如迪马所说,使用智能指针将是一个好主意。一个好的选择可能是来自Boost或TR1的shared_ptr。 – 2010-05-15 02:15:30

4

C++是不是Java。您不能将派生类型存储在基本类型的变量中。例如:

Base b = Derived(); 

将只存储变量b中Derived的基部。为了得到多态行为,你就需要使用指针,动态创建的派生类:

Base * b = new Derived(); 

这同样适用于C++的容器 - 你需要:

map <string, Base *> m; 

所有这一切都应该是在每本介绍性的C++教科书中都有介绍 - 您正在使用哪一种?

+3

请记住,您还需要在完成地图时删除地图条目指向的对象。如果地图在Derived对象之前被销毁,那些Derived对象就是内存泄漏! – 2010-05-13 21:42:32

+1

谢谢!我正在阅读的这本书(德文版)并没有深入到STL,而是讲述了所有基本的东西。我误解了一些东西,但是知道这很清楚! – 2010-05-13 22:32:44

4

遇到 “slicing”。为了让虚拟函数正常工作,您需要使用指针或引用来调用它们。换句话说,你应该map包含指向ClassA

map<string, ClassA *> test_map

请记得delete他们时,你都做了,或者使用智能指针。

这里有更多的切片:hereherehere