无需类型转换的模板化派生类的C ++访问成员

时间:2018-08-23 09:38:53

标签: c++ vector smart-pointers derived-class

是否可以使用指向基类的指针来访问派生类的成员?

// Example program
#include <iostream>
#include <vector>
#include <memory>
#include <string>

class A {
    public:
    std::string x = "this is the wrong x\n";
    };

template <class T>
class B : public A {
    public:
    T x;
    };

int main()
{
    std::vector<std::unique_ptr<A>> vector;
    auto i = std::make_unique<B<int>>();
    i->x = 6;
    vector.push_back(std::move(i));
    for(auto &element : vector){
        std::cout << element->x;
    }
}

在这里,我总是从类A获得输出。我无法进行类型转换,因为我事先不知道该元素是A类型还是B类型。有适当的方法做到这一点吗?

2 个答案:

答案 0 :(得分:2)

正确的方法是制作一个virtual函数来执行类似打印的任务。

class A {
public:
    std::string x = "this is the wrong x\n";
    virtual ~A() = default;
    virtual void print() const { std::cout << x; }
};

template <class T>
class B : public A {
public:
    T x;
    virtual void print() const override { std::cout << x; }
};

int main()
{
    std::vector<std::unique_ptr<A>> vector;
    auto i = std::make_unique<B<int>>();
    i->x = 6;
    vector.push_back(std::move(i));
    for(auto &element : vector){
        element->print();
    }
}

答案 1 :(得分:0)

如果您有一个指向基类的指针,则只能访问在该基类上定义的内容(不进行类型转换)。就编译器所知,它基类的实例,而没有

多态行为涉及使用virtual函数-派生类可以更改在调用基类的virtual函数时调用哪个函数。请注意,该机制对于成员不存在(关于成员您将作哪些更改?只有类型,而在派生类中进行更改则毫无意义)。因此,使用指向应该具有自定义行为的基类的指针,唯一有意义的事情就是调用其虚拟函数。

现在,您可能会认为“好吧,我将通过虚拟函数访问x”,但是这里的问题是,当您在虚拟机中声明虚拟函数时,必须指定所涉及的类型。基类已经。这是有道理的:编译器需要知道函数涉及哪些类型,甚至是虚函数。如果它们是“兼容的”,则只能在覆盖函数中传递和返回不同的类型-有关更多信息,请参见covariance and contravariance

因此,除非您所有的T是协变的,否则虚函数也无法帮助您。

此概念的核心缺陷是,您希望非模板化函数中具有某种类型(即element->x)取决于某些对象(例如element)的动态类型。这是不可能的,因为编译器必须在编译时知道每个表达式的类型。因此,您必须以不同的方式处理问题。