从基类c ++的向量中的派生类调用虚拟方法[重复]

Posted

技术标签:

【中文标题】从基类c ++的向量中的派生类调用虚拟方法[重复]【英文标题】:Calling virtual method from derived class in vector of base class c++ [duplicate] 【发布时间】:2013-07-01 02:26:21 【问题描述】:

在 BaseClass 类中我有一个公共函数:

virtual void Call();

在派生类 Archer 内部,我有以下功能:

void Call() cout << "whatever" << endl; ;

我还设置了一个矢量:

vector<BaseClass> classes;

其中我推送了从 BaseClass 派生的 3 个类。问题似乎(对我来说,我可能错了)是我从对 BaseClass 的引用调用 Call(),即使我通过以下方法将它们推入向量:

BaseClass Player::CharChoice(string character)

    if(character == "Archer") return *new Archer();
    else if(character == "Knight") return *new Knight();
    else if(character == "Sorcerer") return *new Sorcerer();
    else cerr << "CHARACTER NOT DEFINED" << endl;
;

for(int c = 0; c < chars.size(); c++)

    classes.push_back(CharChoice(chars[c]));

如果我改为设置一个变量,例如:

Archer *archer = new Archer();

并调用 Call(),它会按照我的意图工作。我对 C++ 还很陌生,无法想出解决方案。

【问题讨论】:

多态性仅适用于指针和引用。但是您将BaseClass 作为来自CharChoice 的副本返回,并且当您将其推送到向量时会制作另一个副本。每个副本都将对象切回 BaseClass 对象。 *new T() 几乎总是一个错误。使用智能指针。 【参考方案1】:

当您在堆栈而不是堆上创建对象时,继承的大部分价值都会丢失。虚函数是您丢失的东西之一,如果您希望虚函数调用正确的函数,您必须将对象作为指针或引用传递并使用new 来创建它。

Base * b = new Derived();    // or  
Base & b = * new Derived();  

向量必须存储引用或指针。

vector<BaseClass*> classes;
vector<BaseClass&> classes;

根据大众需求,处理此问题的最简单方法是std::shared_ptr

vector<shared_ptr<BaseClass>> classes;

其中一个将像这样创建:

shared_ptr<BaseClass> ptr(new BaseClass);

基本上一个 shared_ptr 会处理烦人的内存管理任务

如果您需要多个 ptr 指向同一个对象,shared_ptr 很好,如果不需要,您可以使用std::unique_ptr

vector&lt;unique_ptr&lt;BaseClass&gt;&gt; classes;

像这样创建:

unique_ptr&lt;BaseClass&gt; ptr(new BaseClass);

如您所见,语法与 shared_ptr 非常相似,因此转换很容易

【讨论】:

鉴于该问题被标记为 C++11,我发现在答案中包含有关智能指针的词非常可取。 @jogojapan 我试试看 你想更喜欢unique_ptr而不是shared_ptr @Griwes 你能解释一下原因吗? @aaronman,性能低于shared_ptr。和适当的语义。如果所有权是唯一的,请始终使用unique_ptr,并且除非明确标记,否则始终假定唯一的所有权。

以上是关于从基类c ++的向量中的派生类调用虚拟方法[重复]的主要内容,如果未能解决你的问题,请参考以下文章

从基类调用派生类的隐藏(非虚拟)方法

从基类向下转换时是不是可以调用派生对象的虚拟方法?

派生类不从基类继承重载方法

派生自抽象基类并调用另一个类中的方法的 C++ 包装类,该类也派生自抽象基类

C#:基类中的受保护方法;无法使用来自另一个类的派生类对象进行访问[重复]

在Java中,如何从派生类中的重写方法调用基类的方法?