c++ - 如何从包含基类指针的容器中调用派生类函数(基于其类型)?

标签 c++ c++11

我继承自基类以创建两个不同的派生类(Derived1 和 Derived2),然后将它们放入一个 vector 中。假设我想根据类的类型调用派生类的函数。

伪代码:

if holder[1] stored Derived1 then I want to call GetZ() 
else if holder[1] stored Derived2 then I want to GetFlag(). 

一次尝试:

#include <iostream>
#include <memory>
#include <vector>

class Base {
 public:
  Base(int x, int y) : x_(x), y_(y) {}

  int GetX() { return x_; }
  int GetY() { return y_; }

 private:
  int x_;
  int y_;
};

class Derived1 : public Base {
 public:
  Derived1(int x, int y, int z) : Base(x, y), z_(z) {}

  int GetZ() { return z_; }

 private:
  int z_;
};

class Derived2 : public Base {
 public:
  Derived2(int x, int y, bool flag) : Base(x, y), flag_(flag) {}

  bool GetFlag() { return flag_; }

 private:
  bool flag_;
};

std::vector<std::shared_ptr<Base>> holder;
void print();
int main() {
  holder.push_back(std::make_shared<Derived1>(3, 4, 5));
  holder.push_back(std::make_shared<Derived2>(6, 7, true));

  print();
}

void print(){

  for(auto& it : holder){
    // call this if "it" is Derived2
    // else call it->GetX()
    // currently this gives compilation error 
    // because of object slicing
    std::cout << it->GetFlag() << std::endl;
  }

}

最佳答案

for(auto& it : holder){
  if (auto* D1 = dynamic_cast<Derived1*>(it->get())) {
    std::cout << D1->GetZ();
  } else if (auto* D2 = dynamic_cast<Derived2*>(it->get())) {
    std::cout << D2->GetFlag();
  }
  std::cout << std::endl;
}

动态转换通常是代码异味,表明您的界面 Base 缺少功能。动态转换后,您的界面将从 Base 状态变为整个类型层次结构的布局和内容。

相反,添加:

virtual boost::optional<int> GetZ() { return {}; }
virtual boost::optional<bool> GetFlag() { return {}; }

Base,并在 derived 中覆盖。

for(auto& it : holder){
  if (auto Z = it->GetZ()) {
    std::cout << *Z;
  } else if (auto flag = it->GetFlag())
    std::cout << *flag;
  }
  std::cout << std::endl;
}

现在我们不再关心我们使用哪个特定的派生类型来实现 ZFlag

来自 this SO answer有一个link to a reference std::optional implementation使用boost软件许可证,是一个头文件。

关于c++ - 如何从包含基类指针的容器中调用派生类函数(基于其类型)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45446072/

相关文章:

c++11 - 编译器声明的隐式移动构造函数

c++ - 使用循环变量作为 C++ 数组的索引

c++11 - 如果我有 T&& temp = std::move(other);然后在按值接受 T 的函数上使用它

C++ Armadillo 稀疏矩阵类型转换

c++ - Concepts TS 中是否有任何预定义的概念?

c++ - 我真的需要为 const 对象实现用户提供的构造函数吗?

c++ - 此结构的生命周期和内存设置

c++ - 不可 move -不可复制对象的 vector 的 move 分配不编译

c++ - 如何在 C++ 中实现接口(interface)?

c++ - C++ 编译器是否根据使用情况内联函数?