将变量作为基类对象迭代,同时转换为子类并在 C++ 中使用它们的覆盖方法

Posted

技术标签:

【中文标题】将变量作为基类对象迭代,同时转换为子类并在 C++ 中使用它们的覆盖方法【英文标题】:Iterate through variables as Base class objects while casting to Child classes and use their overriden methods in C++ 【发布时间】:2020-12-07 22:51:56 【问题描述】:

我正在尝试做一些我觉得应该更直接的事情,或者我的 Java 知识可能会干扰,但我无法弄清楚。

我要做的就是创建一个vector<A> as aa, bb, cc,其中bbcc 是基类A 的子实例。每个 Child 类使用相同的函数名但具有不同的实现。所以我想做的是在迭代期间调用那个实现。

这是我的尝试。

#include <iostream>
#include <vector>

class A 
  public: 
    virtual ~A() = default;
;

class B: public A 
  public:
    int h() 
      return 2;
    
;

class C: public A 
  public:
    int h() 
      return 3;
    
;

int main() 
  std::cout << "hello world" << std::endl;
  
  // Inheritance
  A aa;
  B bb;
  C cc;

  std::vector<A> as aa, bb, cc;

  for (A child: as) 
    if (typeid(B) == typeid(child)) 
      std::cout << "child is a B" << std::endl;
      B* child_b_p= static_cast<B*>(&child);
      std::cout << child_b_p -> h() << std::endl;
    
    
    if (typeid(C) == typeid(child)) 
      std::cout << "child is a C" << std::endl;
      C* child_c_p= static_cast<C*>(&child);
      std::cout << child_c_p -> h() << std::endl;
    
  

  return 0;

我期待

child is a B
2
child is a C
3

我只看到hello world。在这种情况下,对象切片的可能解决方法是什么?

【问题讨论】:

【参考方案1】:

您正在遭受object slicing 的困扰。多态性仅在使用指向对象的指针/引用时才有效,而你不是。

另外,这段代码:

if (typeid(B) == typeid(child)) 
    ...
    B* child_b_p = static_cast<B*>(&child);
    ...

应该写成使用dynamic_cast 而不是typeid()

试试这个:

#include <iostream>
#include <vector>

class A 
  public: 
    virtual ~A() = default;
;

class B: public A 
  public:
    int h() 
      return 2;
    
;

class C: public A 
  public:
    int h() 
      return 3;
    
;

int main() 
  std::cout << "hello world" << std::endl;
  
  // Inheritance
  A aa;
  B bb;
  C cc;

  std::vector<A*> as &aa, &bb, &cc;

  for (A* child : as) 
    if (B* child_b_p = dynamic_cast<B*>(child)) 
      std::cout << "child is a B" << std::endl;
      std::cout << child_b_p->h() << std::endl;
    
    
    if (C* child_c_p = dynamic_cast<C*>(child)) 
      std::cout << "child is a C" << std::endl;
      std::cout << child_c_p->h() << std::endl;
    
  

  return 0;

【讨论】:

以上是关于将变量作为基类对象迭代,同时转换为子类并在 C++ 中使用它们的覆盖方法的主要内容,如果未能解决你的问题,请参考以下文章

在c#中将基类动态转换为子类

c++ 在基类类型的向量中调用子类方法

通过 C++ 中的 std 迭代器将基类转换为派生

C++中,建立子类对象的时候,会调用基类的构造函数,

C++ 类型将基础对象转换为派生对象

多态的课后总结