2

最近我决定在一个项目中工作,我需要一个对象,它可以是任何数据类型(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->get() 的错误。我在网上搜索找到这段代码(dynamic_cast):

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

正如您所看到的,这对我来说: TypedDynamicVariable* < int > * 和 dynamic_cast*>(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 为我指明正确的方向。

谢谢。

4

3 回答 3

0

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

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

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

并且您当前的包装器(大部分)在多态性方面无用 - 您可以拥有一个指向基类的指针容器,但无法意识到其中存储的内容......所以您无法get()从这个存储中取出任何东西/知识存储在其中。你必须提供一些方法来做到这一点。他们必须以某种方式使用 RTTI……所以就性能而言,它远非完美……更好用boost::variant

于 2013-01-22T15:33:08.903 回答
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你可能不得不做类似的事情。

于 2013-01-22T15:44:48.353 回答
0

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

我不是 boost::variant 或 boost::any 的忠实拥护者(即使它们有用!),它有时是解决设计问题的一种太简单的方法。

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

  • 如果是,那么您也应该考虑对返回的类型进行继承:例如,该方法get()返回母类的指针,GeneralReturnType而子实现返回派生自的类的指针GeneralReturnType
  • 如果不是,那么您不应该get()DynamicVariable类中调用:不同的返回类型没有共同的含义,因此该get()方法具有不同的含义,具体取决于所TypedDynamicVariable考虑的类。因此,要调用该get()方法,您应该知道您拥有哪个派生类(也许多态不是您想要的,实际上......)。
于 2013-01-22T16:20:37.633 回答