dynamic_cast转换为相同类型不会检查对象的类型
dynamic_cast to the same type does not check type of object
我正在尝试确定由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(如Array<Object*>
和Array<String*>
(之间的浅层转换,我希望通过在每个元素访问时进行动态类型检查来保证最小的类型安全性,例如:
#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*>
的情况下失败了,尽管我不确定是否可以在不使用repret_cast的情况下将非Object插入到Array<Object*>
中。
根据您的示例,听起来您有一个浅拷贝数组,有人可以欺骗它来包含不同的类型。我认为这个问题的"正常"解决方案是让用户很难做到这一点(即不提供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
应该可以实现您的目标。
让我看看我是否满足了您的需求,并在此过程中提出了一些建议。。。
Array<String*> v(10);
似乎这是为了给您一个数组,其中10个String*
s初始化为NULL/0。
Array<Object*> o = v;
创建一个v.size()
/10个Object*
的数组,每个都从v
中的String*s
复制。
o[0] = new Integer(1); // technically illegal but no idea how to check
如果这是非法的,那么您显然希望防止覆盖Object*
s,因为这会更改运行时类型。。。
- 您需要截取
operator=
来实现before/after类型比较 - 要拦截
operator=
,需要o[0]
返回一个可以指定其operator=
的类型- 让
o[0]
返回Object*永远不会起作用,因为指针不是用户定义的类:您不能修改operator=
的行为 - 您必须让o[0]返回一个代理对象——这里几乎是一个迭代器,尽管语义和赋值类型断言与标准容器迭代器不同
- 让
这就引出了:
Array<String*> w = o; // this fails with an exception
我认为这只是失败了,因为上面的o[0] = new Integer()
并没有首先失败,而且例外是您故意测试元素类型是否符合预期:如果您使用所讨论的代理对象来阻止Integer进入Array<Object*>
,那么这里没有问题。
String* str = v[0]; // should fail horribly as well
同样,我猜这应该会失败,因为您之前的Integer
作业没有,而且这里没有新的问题。
cout << str << endl;
因此,代理对象似乎是关键。如果你不知道如何写,请告诉我,但我猜你知道…
在C++中,从同一类型到同一类型的dynamic_cast
被定义为无操作,因此它不能在您的示例中"失败"。您可以改用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;
}
只需引入一个带有虚拟析构函数的公共基类。对于空基优化,这可能不会增加任何开销,并且会使dynamic_cast
正常工作。
- 如何检查对象有效
- 什么更有效率?在重载函数中或通过在基类函数中检查对象类型来实现
- Python C API:如何检查对象是否是类型的实例
- 在一个作用域中推送五个对象指针,然后检查对象的布尔值是否为 false,会给出错误
- 检查对象是否是具有模板的类的实例
- 如何检查对象是否是基类类型
- STLS STD :: MAP和STD :: vector;在地图中检查对象类型
- C++是否有现有的方法来检查对象是否是派生类型对象
- 在检查对象类型的情况确实总是符合不良设计的迹象
- 检查对象的类型是否是从特定类继承的
- 如何在C++中检查对象的类?
- 如何检查对象数组是否为空/空
- C++检查对象是否是给定超类的后代
- 如何检查对象属性更新是否存在 std::map 键,否则插入一个新键?
- 检查对象之间的冲突时,列表迭代器不可递增
- (C++)用于检查对象是否在向量/数组/列表/.中的模板
- 映射/集合迭代器不兼容-检查对象是否在映射中
- 崩溃后在gdb回溯中检查C++对象
- 当函数重新调整通过引用传递时检查对象是否存在
- 如何检查对象是否在数组中