C++继承,覆盖时仍然调用基函数

Jea*_*rin 3 c++ inheritance abstraction

我有以下两个类,一个继承自另一个

Class A{
  void print(){cout << "A" << endl;}
}

Class B : A{
  void print(){cout << "B" << endl;}
}
Class C : A{
  void print(){cout << "C" << endl;}
}
Run Code Online (Sandbox Code Playgroud)

然后在另一个课程中我有以下内容:

vector<A> things;
if (..)
  things.push_back(C());
else if (..)
 things.push_back(B());

things[0].print();
Run Code Online (Sandbox Code Playgroud)

这总是打印A
我喜欢它打印B或C取决于我添加到向量中的哪个东西我该
怎么做?
我已经尝试过抽象,但我不完全确定如何在C++中使用它,它并没有为我工作

Joe*_*Joe 8

1)您需要在A类中将print()声明为虚拟.

2)你的矢量不正确 - 你不能在那里存储实际的A类物体; 你将需要存储指向它们的指针以获得正确的行为(并且你必须在以后清理它们)和/或使用类似boost :: shared_ptr的东西.


Geo*_*che 8

如前所述,您需要virtual函数来启用多态行为,并且不能直接按值存储类vector.

当您使用a时std::vector<A>,您将按值存储,因此您添加的对象(例如via)push_back()将复制到an的实例A,这意味着您将丢失对象的派生部分.此问题称为对象切片.

正如已经建议的那样,你可以通过将指针(或智能指针)存储到基类来避免这种情况,因此只有指针被复制到vector:

std::vector<A*> things;
things.push_back(new B());
// ... use things:
things[0]->print();

// clean up later if you don't use smart pointers:
for(std::vector<A*>::iterator it = things.begin(); it != things.end(); ++it)
    delete *it;
Run Code Online (Sandbox Code Playgroud)

  • 请记住,如果在使用矢量期间发生任何异常,您将会发生泄漏.解决方案当然是使用Boost的指针库.但是,如果这是不可能的,一个非常简单的解决方案可能是创建一个`pointer_vector <T>`类,它有一个私有的`vector <T>`你可以用`get`函数访问.这个包装器的析构函数执行删除操作.现在保证删除对象. (2认同)