1

我正在尝试实现一个 C++ 类,它的value字段可以指向任何东西(有点像 boost::any)。目前我执行以下操作:

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?其他...),以便 *value 正确转换为 T 对象,如果 value 最初不是这种类型,则会引发异常?

谢谢

4

3 回答 3

4

你不能取消引用 a 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&( constreference to ) 的版本以避免复制。T

于 2012-08-10T20:13:52.000 回答
1

which cast (static_cast?dynamic_cast? other...) 我应该使用这样 *value 被正确转换为 T 对象

如果您必须进行此转换,那么您应该使用static_cast,它通常旨在(除其他外)反转任何标准转换。从任何对象指针类型到 都有一个标准转换void*,并且您的 getter 将其反转,因此请使用为此设计的转换:

return *static_cast<T*>(value);

您还应该从构造函数中删除 C 样式转换,或者将其替换为 a static_cast

Areinterpret_cast也可以,但是“过大”。一般来说,您应该使用尽可能严格的强制转换,同时仍然执行您需要的转换。

如果 value 最初不是这种类型,则会引发异常

你在那里不走运 - 一旦你将指针转换为void*. 您的代码依赖于调用者以getValue正确的类型调用。例如,考虑如果原始类型是char- 在 C++ 中只有一个字节,没有为任何类型信息留出空间来允许编译器检查getValue.

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

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

正如您所说,您的课程旨在有点像boost::any,并且getValue就像any_cast。您可以查阅该类的源代码和文档,以了解执行您想要的操作所需的技巧。如果有一个简单的方法来做到这一点,那么boost::any将是一个简单的类!

于 2012-08-11T00:48:48.023 回答
0

你不能。C++ 不提供这种机制,至少不直接提供,对于void*. Avoid*没有计算机需要确定它是什么的任何信息,并且尝试“检查”它是否是有效的“随便你投它”是不可能的,因为没有特定的标志。

不过,有一些选择。第一种是使用某种通用基类,类似于 Java 的 Object,并从中派生所有其他类。dynamic_cast现在将以您想要的方式工作(NULL如果对象不是您将其转换为的类的有效对象,则返回)。

另一个是简单地跟踪你自己是什么类型的对象。这意味着void*用另一个值来增加它,该值告诉您需要将其转换为什么。

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

于 2012-08-10T20:14:52.560 回答