我正在尝试确定T *指针指向的对象是否真的是T对象,或其他一些不相关的类型。我尝试了dynamic_cast,但它不是没用,它返回指针本身而不是null,即使很明显它没有指向有效的T对象:
Object* garbage = reinterpret_cast<Object*>(0x12345678);
if( dynamic_cast<Object*>(garbage) == NULL ){
cout << "Expected behaviour (by me)" << endl;
}else{
cout << "You've got to be kidding me" << endl;
}
是否有针对此的解决方法或其他解决方案?我已经尝试在dynamic_cast之前转换为void *和char *无效,因为我想接受子类,所以typeid是不够的。
某些上下文:我正在编写一个自定义Array类,在不同类型的数组之间实现浅层转换,例如Array<Object*>
和Array<String*>
,我想通过动态保证最小的类型安全性在每个元素访问时键入check,例如:
#define DEBUG
Array<String*> v(10);
Array<Object*> o = v;
o[0] = new Integer(1); // this is technically illegal but no idea how to check
//Array<String*> w = o; // this fails with an exception
String* str = v[0]; // but this should fail horribly as well
cout << str << endl;
转换为Object *,然后在很多情况下对Object *进行类型检查,但在Array<Object*>
的情况下失败,但我不确定是否可以插入非 - 在不使用reinterpret_cast的情况下将对象转换为Array<Object*>
。
答案 0 :(得分:1)
根据你的例子,听起来你有一些浅拷贝数组,有人可以欺骗它们包含不同于它们应该包含的类型。我认为这个问题的“正常”解决方案是让用户难以做到(即不提供Array<T>
和Array<U>
之间的转换)。但是,如果你对自己的想法感兴趣,我认为这样可行:
template<typename Subclass>
class Array {
public:
// ...
Subclass *operator [] (size_t index) {
assert( index < size_ );
assert( dynamic_cast<Subclass*>(static_cast<Object*>(internal_[index])) != NULL );
// ...
}
// ...
private:
size_t size_;
Subclass **internal_;
};
您可以执行一些模板元魔术和静态断言,以确保Subclass
实际上是Object
的子类(具体如何是一个完全不同的主题)。一旦完成,请向下转换为Object *,然后使用dynamic_cast备份到Subclass
,这样可以实现目标。
答案 1 :(得分:1)
让我看看我是否关注你的需求,并在此过程中提出一些建议......
Array<String*> v(10);
似乎这是为了给你一个10 String*
初始化为NULL / 0的数组。
Array<Object*> o = v;
创建一个v.size()
/ 10 Object*
个数组,每个数组都来自String*s
中的v
。
o[0] = new Integer(1); // technically illegal but no idea how to check
如果这是非法的,那么您显然希望防止覆盖更改运行时类型的Object*
...
operator=
以实现前/后类型比较operator=
,您需要o[0]
才能返回您可以指定operator=
的类型
o[0]
返回一个Object *永远不会工作,因为指针不是用户定义的类:你不能修改operator=
行为这将我们带到:
Array<String*> w = o; // this fails with an exception
我认为这只是失败,因为上面的o[0] = new Integer()
没有先失败,并且异常是你故意测试的元素类型满足期望:如果你使用代理对象,那么这里没有问题阻止整数进入Array<Object*>
。
String* str = v[0]; // should fail horribly as well
同样,我猜这应该失败,因为你之前的Integer
任务没有,而且这里没有新问题。
cout << str << endl;
因此,代理对象似乎很关键。如果你不知道如何写一个,请告诉我,但我猜你做了....
答案 2 :(得分:0)
来自同一类型的dynamic_cast
被定义为C ++中的无操作,因此它不能与您的示例“失败”。您可以改用typeid
运算符。
例如,这个程序很可能崩溃(这是从一个随机地址的对象获取类型信息的“预期”结果):
int main()
{
Object* garbage = reinterpret_cast<Object*>(0x12345678);
if (typeid(*garbage) == typeid(Object))
cout << "Your program thinks this garbage is an actual object!" << std::endl;
}
答案 3 :(得分:0)
简单介绍一个带有虚析构函数的公共基类。使用空基优化,这可能不会增加任何开销,并且会使dynamic_cast
正常工作。