多态性 - 使用模板不确定派生类 - 派生函数返回模板类型

时间:2013-01-22 15:27:33

标签: c++ templates boost polymorphism variant

最近我决定开展一个项目,我需要有一个对象,可以是任何数据类型(uint8,unint16,uint32或unint64)(我可能想添加这些只是数字,并且只会是+, - ,*,/,<<,>>。我查看了Boost :: variant,但是在尝试之后,由于无法正确检索数据,我对此感到气馁。应用访问者?所以我已经看过其他方法来模仿这个。

在这一点下面是实验,似乎错了,非常错误:

(我想说我对多态/继承不太深入,所以提前抱歉) 我试图创建一个基础对象,然后将基础对象设置为派生类 - 派生模板类,这是我选择的数据类型(uint8,uint16,uint32或uint64)之后,我可以简单地检索数据我以前使用方法get():

设置
DynamicVariable *a = new TypedDynamicVariable<unsigned int>(12345); 
std::cout << a->get() << std::endl; 
delete a; 

或:

DynamicVariable *a = new TypedDynamicVariable<unsigned char>(255);
std::cout << a->get() << std::endl;
delete a;

表示示例:

unsigned int  a = 100;
unsigned char b = 20;
std::cout << a + b << std::endl;

导致:错误C2039:'get':不是'DynamicVariable'的成员

我收到的错误是BASE类中不存在a-&gt; get()。我在网上搜索了这段代码(dynamic_cast):

DynamicVariable *a = new TypedDynamicVariable<int>(12345);
TypedDynamicVariable<int>* p = dynamic_cast<TypedDynamicVariable<int>*>(a);
std::cout << p->get() << std::endl;

如您所见,这:TypedDynamicVariable * &lt;对我来说,int&gt; *和dynamic_cast *&gt;(a)(指定它是INT)会破坏我想要做的事情的整个目的。

以下是我从许多不确定的在线阅读时间中分类攻击的课程。它似乎有我的''解决方案'的大致轮廓'但是我知道有重要内容缺失/需要改进apon,或者实际上多态性不是我想要的/毕竟/不能使用。

class DynamicVariable
{
    public:
        //constructor & virtual destructor
                 DynamicVariable() {}
        virtual ~DynamicVariable() {}

};

//unique data
template<typename T>
class TypedDynamicVariable : public DynamicVariable
{
    private:
        T _data;

    public:
        //constuctor
        TypedDynamicVariable    (const T& data) : _data(data) { }

        //prototypes
        void    set             (const T& data) { _data = data; }
        T       get             (void)          { return _data; }
};

如果有人能帮助我理解上述课程的错误并引导我找到一个有效的解决方案,或者使用boost :: variant指出我正确的方向,如果他们真的是我想要的那样。

感谢。

3 个答案:

答案 0 :(得分:0)

如果特定类型在编译时是众所周知的(您必须提供列表来实例化它),您可以使用boost::variant。并且只有 类型可以存储在变体中。那么您可以使用访问者对存储的数据进行smth(另请参阅which()成员函数)。

或者,您可以对所包含的数据类型使用boost::any w / o任何限制。

编写自己的变体(几乎)无法用传统的OOP实现:因为你需要编写一个具有不同返回类型的get()成员(在编译时未知)。(这在C ++中是不可能的)。

并且你的当前包装器(大多数)在多态性方面没用 - 你可以有一个指向你的基类的指针的容器,但是无法实现存储在里面的内容......所以你不能get()任何东西从这个存储库中获取存储在其中的知识。你必须提供一些方法来做到这一点。并且他们必须以某种方式使用RTTI ......所以在性能方面它将远非完美......更好地使用boost::variant

答案 1 :(得分:0)

DynamicVariable *a = <some initialisation>
std::cout << a->get() << std::endl; 
delete a; 

不起作用,因为编译器必须知道如何在不知道派生类型a->get()实际指向的内容的情况下调用a。因此,只考虑属于a声明(静态)类型的成员,而get不是其中之一。
这与Boost.Variant和Boost.Any也面临同样的问题。

最后,它归结为一件简单的事情:如果您不知道当前存储在boost::variant<> / boost::any / DynamicVariable中的值的类型,那么你无法获得这个价值 对于Boost.Variant,您使用boost::get<type>(variant)检索值。对于Boost.Any,您使用boost::any_cast<type>(any)检索值。对于DynamicVariable,你可能需要做类似的事情。

答案 2 :(得分:0)

为了能够从母班get()调用DynamicVariable,您需要在此处定义此方法,如虚拟(在您的情况下为纯粹)。所以问题是:get()中的DynamicVariable方法会返回什么类型?不要试图用模板找到技巧,虚拟方法也不能成为模板。

我不是boost :: variant或boost :: any的忠实粉丝(即使有用!),它有时也是解决设计问题的简单方法。

作为替代方案,我会考虑您的应用程序(我想您的示例已经简化)。问自己以下问题:不同的类型是否具有共同的含义?

  • 如果是,那么你应该考虑对返回的类型进行继承:方法get()返回一个母类的指针,比如GeneralReturnType,而子实现返回指针类的指针源自GeneralReturnType
  • 如果不是,那么您就不应该从get()类调用DynamicVariable:不同的返回类型没有共同的含义,因此get()方法具有不同的含义,具体取决于考虑了TypedDynamicVariable个班级。要调用get()方法,您应该知道您拥有哪个派生类(可能多态性不是您想要的,确实......)。