2012-08-10 140 views
1

我试图实现一个带有value字段的C++类,它可以指向任何东西(有点像在boost :: any中)。目前,我做到以下几点:右键投给void *指针

class MyClass { 
    void* value; 
    template<typename T> 
    Myclass(const &T v) { 
    value = (void*)(new T(v)); 
    } 
}; 

现在的问题是实现创造内在价值与正确类型副本的getValue()操作:

template<typename T> 
T getValue() { 
return *value; 
} 

这不能因为我的工作试图解除一个void *指针。我想知道哪个类型的转换(static_cast?dynamic_cast?other ...)我应该使用*值正确转换为T对象,并且如果value本来不是这种类型,那么会引发异常?

感谢

+0

可能的重复[我应该使用static_cast或reinterpret_cast当投下一个void *任何](http://stackoverflow.com/questions/310451/should-i-use-static-cast-or-reinterpret-cast-什么时候抛出无效) – Griwes 2012-08-11 14:50:45

回答

4

无法取消引用void*,它完全没有意义的。为什么不让这个类通用?然后,你可以有:

template<typename T> 
class MyClass { 
    T* value; 

    MyClass(const T& v) { 
    value = new T(v); 
    } 

    T getValue() { 
    return *value; 
    } 
}; 

确保创建这将释放value也跟着The Rule of Three析构函数。您还可以制作getValue的一个版本,以返回const T&constT的引用),以避免复制(如果不需要)。

+0

我想避免使类通用,因为我需要使用此类的STL容器,以便我可以存储不同类型的对象。 – sunmat 2012-08-10 20:15:55

+1

@sunmat:那么,你想要什么,你可以有两个不同的东西:)。你的设计没有意义,所以把它扔掉。即使这样做,你会失去所有类型的安全。也许有更好的方法来解决手头的问题。与其要求我们解决你提出的解决方案中最后10%毫无意义的解决方案,如何紧紧描述你正试图解决的高层次问题?可能存在你没有考虑过的完全不同的方法。 – 2012-08-10 20:18:02

+0

我正在处理的应用程序读取包含诸如<参数名称=“something”value =“42”type =“int”/>的行列表的XML文件。这些参数需要存储在某个地方。最后,调用copy_value(“name”,address)函数,该函数应该将该参数的值(如果它存在于XML文件中)复制到指定的地址。就这样。我目前的实现涉及一个大型交换机匹配指定的类型,并返回该类型的大小用于memcpy,我只是想找到一个更优雅的解决方案。 – sunmat 2012-08-10 20:27:00

0

你不能。 C++不提供这种机制,至少不是直接的,不适用于void*。 A void*没有任何信息,计算机将需要确定它是什么,并试图“检查”,如果它是一个有效的无论你投它它是不可能的,因为没有特定的标志为那。

虽然有选择。首先是使用某种通用基类,类似于Java的Object,并从中派生出所有其他类。 dynamic_cast现在将以您想要的方式工作(如果对象不是您将其投放到的类的有效对象,则返回NULL)。

另一种方法是简单地跟踪自己是什么类型的对象。这意味着用另一个值来增加void*,这个值告诉你需要将它投射到什么位置。

但实际上,这些东西都不是我的好主意。我认为你的设计中几乎有一些其他方面应该改变,而不是使用这些方面。使用模板,如@EdS。建议,例如,是一个非常好的选择。

+0

您可以使用static_cast <>从void *进行强制转换。此外,委员会将允许reinterpret_cast <>从void void * for C++ 0x – djf 2012-08-10 20:17:30

+2

@djf:是的,您可以使用'static_cast'或(稍后)'reinterpret_cast' - 显式地不提供这个问题所要求的安全机制。他们只是将所要求的位解释为所请求的类别,而不管其做了多少意义。 – KRyan 2012-08-10 20:18:37

+0

表示同意。我已经撤销了我的downvote – djf 2012-08-10 20:21:46

1

其投(的static_cast?dynamic_cast的?等...)我应该用这样*值被正确地转换成一个T类型的对象

如果你必须这样做转换,那么你应该使用static_cast一般来说,它旨在(除其他外)反转任何标准转换。有任何对象的指针类型void*标准转换,和你的getter逆转,所以使用专为演员:

return *static_cast<T*>(value); 

你也应该从您的构造函数中删除C样式转换,或更换也有static_cast

A reinterpret_cast也可以工作,但是“矫枉过正”。一般来说,您应该尽可能使用尽可能严格的演员阵容,同时仍然执行所需的转换。 C++一般不能告诉一下原始类型的对象是,一旦你 - 如果值最初并不是这种类型

你的运气了那里的

,并抛出一个异常将指针投射到void*。您的代码依赖于呼叫者以正确的类型呼叫getValue。例如,考虑如果原始类型为char会发生什么情况 - 这只是C++中的一个字节,没有空间留出任何类型信息,以便编译器检查getValue中的转换。

dynamic_cast在某些有限的情况下会检查类型,但由于您的模板是完全通用的,因此这些有限的情况可能不适用。

如果你不喜欢这个,除了对象指针之外,你可以改变你的类来存储一个指向type_info对象的指针(由于使用了typeid运算符)。请参阅标准标题<typeinfo>。然后,您可以将构造函数中的类型为Ttype_info对象与getValue中的T类型的type_info对象进行比较,如果它们不匹配,则会抛出。

正如你所说,你的班级打算有点像boost::anygetValue就像any_cast。您可以查阅该课程的源代码和文档,查看所需的技巧以实现您的目标。如果有一个简单的方法来做到这一点,那么boost::any将是一个简单的课程!