2017-11-11 63 views
1

下面是一个示例程序是什么我谈论:C++ - 呼儿方法将覆盖在家长的名单

#include <iostream> 
#include <list> 

using namespace std; 

class Thing { 
    public: 
     virtual void jump() { cout << "Called from Thing class" << endl; } 
}; 

class Car: public Thing { 
    public: 
     virtual void jump() { cout << "Vroom vroom; imma car biotch" << endl; } 
}; 

int main(int argc, char* argv[]) { 

    Car myCar; 

    list<Thing> myList; 

    myList.push_back(myCar); 

    std::list<Thing>::iterator iterator; 
    for (iterator = myList.begin(); iterator != myList.end(); ++iterator) { 
     iterator->jump(); 
    } 

    return 0; 
} 

输出:

Called from Thing class 

我想要什么要做的是列出“事情”。我希望能够从Thing类中添加子类的实例;那么我希望能够从迭代器中调用它们的覆盖函数。

唯一的问题是,即使在使用“虚拟”关键字时,迭代器也会使用Thing :: jump函数,而不是Car :: jump函数。

我该怎么做才能使它不仅适用于Car,而且还包括Thing,Car等所有覆盖“跳转”功能的潜在子类。

+5

多态性需要一个指针或引用的位置。你正在做的是切分你的派生对象,以便它变成简单的基础类型对象。 –

+0

术语检查:它是“覆盖”和“重写”。 – molbdnilo

回答

0

在C++值是他们说他们是。你有一个Thing列表不是一个列表Thing或派生类型。

当您在列表中插入某些东西时,会创建它的一个副本。在插入派生类型实例的情况下,这会复制对象的部分,即所谓的对象切片(将部分切掉)。

存在多种方式来存储多态数据,但基本类型的实例不是其中之一。例如,您可以将std::unique_ptr<Base>存储在您的列表中,例如:

例如,您可以将std::unique_ptr<Base>存储在您的列表中。如果这样做,请确保您的基本类型具有虚拟析构函数,以避免在默认的删除器中删除未定义的行为。

#include <iostream> 
#include <list> 
#include <memory> 

class Thing { 
public: 
    virtual void jump() { std::cout << "Called from Thing class\n"; } 
    ~Thing(){} 
}; 

class Car: public Thing { 
public: 
    virtual void jump() { std::cout << "Vroom vroom; I am a car\n"; } 
}; 

然后在主:

std::list<std::unique_ptr<Thing>> myList; 

myList.push_back(std::make_unique<Car>()); 

for(auto&& ptr:myList){ 
    ptr->jump(); 
} 
+0

我得到:** main.cpp:18:15:错误:'unique_ptr'不是'std'的成员** – Griffort

+1

@Griffot您是否将您的编译器设置为支持C++ 11?如果没有,请看看[这里](https://stackoverflow.com/questions/10363646/compiling-c11-with-g) – HJuls2

+0

@griff也是'#include '它的定义。 – Yakk