如何推导派生类的类型

时间:2016-10-25 17:59:38

标签: c++ class templates

假设我有一个基础抽象类:

class Base  
{
 public:
 virtual ~Base(){};
 };

并从它模板类派生:

template<typename T>
class Derived : public Base 
{
 public:
    void function(); 
};

另一个类Test,它具有Base类对象的向量

 class Test
 {
 public:
 vector< Base* > base_vector;
 };

问题1:如果我们有一个指向Base类对象的指针向量,那么它们也可以填充指向Derived类的指针,对吗?

所以,现在让我说从现有的测试类中访问这个向量,该测试类以前填充了指向派生类类型对象的指针

void (Test test)
{
    vector<Base*> objects = test.base_vector;
}

问题2:是否可以推导出衍生对象的类型名称,指针指向哪个? (派生类是模板)

OR是否可以调用Derived类中定义的function(),而不关心Derived类的类型?

如果没有,那么应该对这些类中的任何一个进行哪些最小的更改?

2 个答案:

答案 0 :(得分:1)

如果我正确理解您的问题,那么您需要使用虚拟功能。如果要调用对象上的函数并确保调用正确类型的函数,请将 @Html.TextBox("Napisz", null, new { @class = "ostatni" }) 虚拟化。所以你需要在function课程中声明它。此外,您需要使矢量成为Base指针的向量。然后当你在向量的对象上调用Base时,如果对象确实是派生类型,它将从派生类调用该函数。

这样你就不需要找出对象的类型了,你只需调用虚函数,它就会找出它是什么类型的对象并调用正确的函数。

答案 1 :(得分:1)

我不确定我是否理解您的需求,但是您的代码修改是否适合您?这样您就可以根本不需要推断类型,或者您可以获得一个虚拟type()方法,它将为您返回一个枚举,其中包含每种类型的一些唯一值。

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

class Base {
public:
  virtual void function() = 0;
  virtual ~Base() = default;
};

template <class T> class Derived : public Base {
public:
  void function() override {
      // to produce some output
      std::cout << typeid(T).name() << std::endl; 
  }
};

class Test {
public:
  std::vector<std::unique_ptr<Base>> objects;
};

int main() {
  Test test;
  test.objects.push_back(std::make_unique<Derived<int>>());
  test.objects.push_back(std::make_unique<Derived<std::string>>());
  for (auto &ptr : test.objects) {
      ptr->function();
  }
}

此问题的替代解决方案是使用variant类,例如boost::variant或std :: experimental :: variant(如果标准库已有)。这样您就不需要在Base类中拥有virtual function()boost::variant具有返回您的which()方法和类型列表中的整数类型。一个例子:

#include <boost/variant.hpp>
#include <iostream>
#include <memory>
#include <string>
#include <vector>

class Base {
public:
  virtual ~Base() = default;
};

template <class T> class Derived : public Base {
public:
  void function() {
    std::cout << typeid(T).name() << std::endl;
  }
};

class Test {
public:
  std::vector<boost::variant<Derived<int>, Derived<std::string>>> objects;
};

int main() {
  Test test;
  test.objects.push_back(Derived<int>());
  test.objects.push_back(Derived<std::string>());
  for (auto& obj : test.objects) {
    switch (obj.which()) {
      case 0:
        boost::get<Derived<int>>(obj).function();
        break;
      case 1:
        boost::get<Derived<std::string>>(obj).function();
        break;
    }
  }
  return 0;
}