【问题标题】:C++ / Polymorphism / Virtual Functions / Why is my child class's function not being called? [duplicate]C++ / 多态性 / 虚函数 / 为什么我的子类的函数没有被调用? [复制]
【发布时间】:2015-01-16 01:12:37
【问题描述】:

我环顾四周,大多数问题都涉及为什么要使用虚拟,什么是多态等等。我的程序有问题,我想知道WHY子函数没有被调用,以及在这种情况下如何实际CALL子函数。

我可以模拟我的问题:

#include <string>
#include <iostream>
#include <vector>

class BaseA {
  public:
  BaseA(const std::string &n)
    : name(n)
  {
  }

  virtual void print() const
  {
    std::string str("");
    str += name;
    std::cout << str << std::endl;
  }

  protected:
  std::string name;
};

class BaseB : public BaseA {
  public:
  BaseB(const std::string &n, const std::string &v)
    : BaseA(n), value(v)
  {
  }

  void print() const
  {
    std::string str("");
    str += name;
    str += ' ';
    str += value;
    std::cout << str << std::endl;
  }

  private:
  std::string value;
};

int main() {
  std::vector<BaseA> vec;
  vec.push_back(BaseA("cat"));
  vec.push_back(BaseB("cat", "kitten"));

  for(BaseA &obj : vec)
    obj.print();

  return 0;
}


为什么输出是:cat cat?

如何使用 BaseB::print() 将输出更改为“cat cat kitten”?

【问题讨论】:

  • 嗯,我明白了。谢谢@rightføld
  • 这几乎是真的@remyabel。我想在我的辩护中指出,如果您不知道该术语被创造为 SLICING,那么如果不直观地显示它,就很难发现正确的问题。
  • @Ben 这是您关闭投票时的自动评论。无意冒犯。
  • @remyabel 未采取任何措施。以后。

标签: c++ inheritance c++11 polymorphism


【解决方案1】:

正如rightføld 所指出的,您是切片问题的受害者。但是,由于您的问题被标记为 C++11,因此您可以利用 std::unique_ptr

std::vector<std::unique_ptr<BaseA>> vec;
vec.push_back(std::make_unique<BaseA>("cat"));
vec.push_back(std::make_unique<BaseB>("cat", "kitten"));

for(std::unique_ptr<BaseA>& obj : vec)
    obj->print();

很遗憾std::make_unique 直到 C++14 才添加,您可以选择使用 emplace_back

std::vector<std::unique_ptr<BaseA>> vec;
vec.emplace_back(new BaseA("cat"));
vec.emplace_back(new BaseB("cat", "kitten"));

for(std::unique_ptr<BaseA>& obj : vec)
    obj->print();

【讨论】:

  • 这个答案非常有帮助,优雅地解决了我的问题。谢谢@remyabel。
  • 实际的 Slice 何时发生?您能否在回答中指出这一点?是我将对象推到矢量上的那一刻吗?
  • @Ben Learning C++: polymorphism and slicing 可能很有启发性(诚然,它比建议的副本更好地解释了。)
  • 再次感谢@remyabel。我同意它确实解释得更好。真的必须记住 C++ 是多么的多样化,以及它的语法使您与机器多么接近。
  • 注意:如果 emplace_back 导致向量增长并且没有足够的内存,则指定的 emplace 版本可能会泄漏内存。
猜你喜欢
  • 2012-11-16
  • 2018-02-04
  • 1970-01-01
  • 2014-10-13
  • 1970-01-01
  • 2018-07-11
  • 1970-01-01
  • 1970-01-01
  • 2013-09-21
相关资源
最近更新 更多