Dynamic_cast 到相同类型不检查对象的类型
我试图确定 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
#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
,尽管我不确定是否可以在不使用reinterpret_cast的情况下将非对象插入到Array
中。
I am trying to determine whether an object pointed by a T* pointer is truly a T object, or some other, unrelated type. I tried dynamic_cast, however it is less than useless, it returns the pointer itself instead of null even when it is obvious it does not point to a valid T object:
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;
}
Is there any workaround for this, or some other solution? I've tried casting to void* and char* before the dynamic_cast to no avail, typeid is not enough either since I want to accept subclasses as well.
Some context: I'm writing a custom Array class implementing shallow conversion between different kinds of Arrays, like Array<Object*>
and Array<String*>
, and I would like to guarantee a minimal type safety by doing a dynamic type check at every element access, for example:
#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;
Casting to Object*, then doing the type check on the Object* works in a lot of cases, but it fails in the case of Array<Object*>
, though I am not sure whether it is possible to insert something non-Object into an Array<Object*>
without the use of reinterpret_cast.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
根据您的示例,听起来您有浅复制数组,有人可能会欺骗其中包含与应包含的类型不同的类型。我认为这个问题的“正常”解决方案是让用户很难做到这一点(即不提供 Array和 Array 之间的转换) >)。但是,如果您坚定自己的想法,我认为这会起作用:
您可以执行一些模板元魔法和静态断言,以确保
Subclass
确实是Object< 的子类/code> (具体如何是一个完全不同的主题)。一旦解决了这个问题,向下转换为 Object*,然后使用dynamic_cast 返回到
Subclass
应该可以实现您的目标。Base on your example, it sounds like you've got shallow copy Arrays which someone could trick into containing different types than they are supposed to contain. I think the "normal" solution to this problem would be to make that difficult for users to do (i.e. don't provide conversions between
Array<T>
andArray<U>
). But, if you're set in your ideas I think this will work:You can do some template meta-magic and a static assert to make sure that
Subclass
is really a Subclass ofObject
(exactly how is a completely different topic). Once that is out of the way, casting down to an Object* and then back up toSubclass
with a dynamic_cast should accomplish your goal.让我看看我是否满足您的需求,并提出一些建议...
似乎这是为了给您一个包含 10 个 String* 并初始化为 NULL/0 的数组。
创建一个由
v.size()
/ 10 个Object*
组成的数组,每个都从v
中的String*s
复制而来代码>.如果这是非法的,那么您显然希望防止覆盖
Object*
,从而更改运行时类型...operator=
来实现 拦截operator=
之前/之后的类型比较o[0]
返回一个可以指定operator=
的类型o[0]
返回一个 Object* 永远不会起作用,因为指针不是用户定义的类:您无法修改operator=
行为< /里>这给我们带来了:
我认为这只是失败,因为你的
o[0] = new Integer() 上面首先并没有失败,例外是您故意测试元素类型是否满足预期:如果您使用所讨论的代理对象来阻止 Integer 进入 Array
同样,我猜测这应该会失败,因为您之前的 Integer 分配没有失败,并且这里没有新问题。
所以,代理对象似乎很关键。如果您不知道如何写,请告诉我,但我猜您知道......
Let me see if I'm following your needs, and makes some suggestions along the way...
Seems this is meant to give you an array with 10
String*
s initialised to NULL/0.Creates an array of
v.size()
/ 10Object*
s, each copied from theString*s
inv
.If this is illegal, then you obvious want to prevent overwriting of
Object*
s where that changes the run-time type...operator=
to implement the before/after type comparisonoperator=
, you needo[0]
to return a type whoseoperator=
you can specifyo[0]
return an Object* will never work, as pointers aren't user-defined classes: you can't modify theoperator=
behaviourWhich brings us to:
I assume this is only failing because your
o[0] = new Integer()
above wasn't failing first, and that the exception is your deliberate test that the element types meet expectations: no problem here then if you use a proxy object as discussed to stop the Integer getting into theArray<Object*>
.Again, I'm guessing this should fail because your earlier
Integer
assignment didn't, and there's no new problem here.So, the proxy object seems key. Let me know if you don't know how to write one, but I'm guessing you do....
来自和到相同类型的
dynamic_cast
在 C++ 中被定义为无操作,因此它不会在您的示例中“失败”。您可以改用typeid
运算符。例如,这个程序很可能崩溃(这是从随机地址的对象获取类型信息的“预期”结果):
A
dynamic_cast
from and to the same type is defined as a no-op in C++, so it cannot "fail" with your example. You can use thetypeid
operator instead.For instance, this program is very likely to crash (which is the "expected" result for getting type information from an object at a random address):
只需引入一个带有虚拟析构函数的公共基类即可。通过空基优化,这可能不会增加任何开销,并且会使
dynamic_cast
正常工作。Just introduce a common base class with a virtual destructor. With the empty-base optimization, this probably won't add any overhead, and it will make
dynamic_cast
just work.