投射到无效*,结果出乎意料。 [英] Casting to void*, result unexpected.

查看:79
本文介绍了投射到无效*,结果出乎意料。的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述




我在程序中的指针转换方面有点麻烦。

我不明白为什么以下两种情况产生不同的结果。


案例1:

IInterface * pInterface = new CImplementation();

pInterface-> ;方法();


案例2:

void * pInterface = static_cast< void *>(new CImplementation());

static_cast< IInterface *>(pInterface) - >方法();


在这两种情况下,IInterface是一个接口定义类,它没有成员变量,只定义了公共纯虚方法。

CImplementation来自IInterface,它实现了那些纯粹的b $ b虚拟方法。


现在,如果CImplementation只是从IInterface派生的,那么上面两种情况

将以完全相同的方式工作。但是,当CImplementation派生自其他类,其中包含虚拟或纯虚方法时,案例2

将失败。它会导致崩溃主要是因为 - > Method()调用不是
实际调用IInterface :: Method(),具体取决于实际的

继承, - > Method()可以指向另一个

类的纯虚方法。案例1仍然有效。这是为什么?更重要的是,为什么

以上两种情况的工作方式不同?


谢谢,

-

何世明

Hi,

I''m having a little bit of trouble regarding pointer casting in my program.
I don''t understand why the following two cases produce different results.

Case 1:
IInterface *pInterface = new CImplementation();
pInterface->Method();

Case 2:
void* pInterface = static_cast<void*>(new CImplementation());
static_cast<IInterface*>(pInterface)->Method();

In these two cases, "IInterface" is an interface definition class, it
contains no member variables, only public pure virtual methods are defined.
"CImplementation" is derived from IInterface, and it implements those pure
virtual methods.

Now, if CImplementation is derived only from IInterface, the above two cases
will work the exact same way. However, when CImplementation derives from
other classes, which also contain virtual or pure virtual methods, Case 2
will fail. It''ll cause a crash mainly because the ->Method() call isn''t
actually calling IInterface::Method(), depending on the actual
inheritance, ->Method() may be pointed at a pure virtual method of another
class. Case 1 still works. Why is that? And more importantly, why is the
above two cases work differently?

Thanks,
--
He Shiming

推荐答案

*何世明:
[void * cast的意外结果]
...

为什么会这样?
[unexpected result from void* casting]
...

Why is that?




忽略编译器特定的行为只有两件事

你可以使用从类型T转换的void *指针:比较它wrt。

与另一个这样的void *指针相等,并将其转换回T.


你从类型X转换为void *然后再回到Y,那就是

未定义的行为,即使类型X和Y是相关的。

也许你会惊讶的是static_cast可以改变指针

bitpattern(同时不改变概念指针值)。但是,如果你想到这就是它必须如何。考虑:


struct A {int x; };

struct B {int y; }

struct X:A,B {};


X * pX =新X;

A * pA = static_cast< ; A *>(pX);

B * pB = static_cast< B *>(pX);


''pA''指向A子对象的开头,''pB''指向B子对象的开头

;这两个指针不能相等。


-

答:因为它弄乱了人们通常阅读文本的顺序。

问:为什么这么糟糕?

A:热门发布。

问:usenet和电子邮件中最烦人的事情是什么?



Disregarding compiler-specific behavior there are only two things
you can do with a void* pointer casted from a type T: compare it wrt.
equality to another such void* pointer, and cast it back to T.

You cast to void* from a type X and then cast back to Y, and that''s
Undefined Behavior even if the types X and Y are related.

Perhaps what surprises you is that static_cast can change the pointer
bitpattern (while not changing the conceptual pointer value). But if
you think about it that''s how it must be. Consider:

struct A { int x; };
struct B { int y; }
struct X: A, B {};

X* pX = new X;
A* pA = static_cast<A*>( pX );
B* pB = static_cast<B*>( pX );

''pA'' points to the beginning of the A subobject, and ''pB'' points to
the beginning of the B subobject; these two pointers cannot be equal.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?


>忽略编译器特定的行为只有两件事
> Disregarding compiler-specific behavior there are only two things
你可以使用从类型T中转换的void *指针:将它与另一个这样的void *指针进行比较。
它返回到T.
你从类型X转换为void *,然后转回Y,即使类型X和Y相关,也是未定义的行为。


对不起,这是什么意思?我提到它只会在使用
多重继承时失败。然后,如果它是一个未定义的行为,为什么

它可以完美地工作,当使用单继承时?

考虑:

struct A {int x;结构B {int y;结构X:A,B {};

X * pX =新X;
A * pA = static_cast< A *>(pX);
B * pB = static_cast< B *>(pX);

''pA''指向A子对象的开头,''pB''指向
B子对象的开头;这两个指针不能相等。
you can do with a void* pointer casted from a type T: compare it wrt.
equality to another such void* pointer, and cast it back to T.
You cast to void* from a type X and then cast back to Y, and that''s
Undefined Behavior even if the types X and Y are related.
I''m sorry but what does this mean? I mentioned that it only fails when
multiple inheritance is used. Then if it''s an undefined behavior, why does
it work flawlessly, when single inheritance is used?

Consider:

struct A { int x; };
struct B { int y; }
struct X: A, B {};

X* pX = new X;
A* pA = static_cast<A*>( pX );
B* pB = static_cast<B*>( pX );

''pA'' points to the beginning of the A subobject, and ''pB'' points to
the beginning of the B subobject; these two pointers cannot be equal.




我明白你的意思但这不是我想要的。


在我的第一篇文章中考虑案例1,它与IInterface一起使用。类型

指针上的定义,案例2失败,因为在指针重新构建期间发生了一些不好的事情

。我试图使用void *的原因是因为

我不能在这种特殊情况下存储类型定义。在第一个

行中,类分配器不知道它应该使用什么类型。


关于指针本身。指针只是一个地址吗?是否无效*

能够存储任何类型的指针?如果是这样,为什么不投你的工作呢?


谢谢,

何世明



I got your point but this isn''t what exactly I wanted.

Consider case 1 in my first post, it worked with the "IInterface" type
definition on the pointer, case 2 fails because something bad happened
during pointer re-casting. The reason why I''m trying to use void* is because
I can''t store the type definition in this particular case. In the first
line, the class allocator has no idea about what type should it use.

Regarding the pointer itself. Isn''t the pointer just an address? Isn''t void*
capable of storing any kind of pointers? If so, why won''t casting work?

Thanks,
He Shiming


*何世明 < mailbill(NOSPAM)@ 21cn.com.nospam>:
* "He Shiming" <mailbill(NOSPAM)@21cn.com.nospam>:
忽略编译器特定的行为只有两件事你可以用虚空做*从类型T转换的指针:将它与另一个这样的void *指针进行比较,并将其转换回T.
从类型X转换为void *然后转换回Y ,即使X和Y类型相关,这也是未定义的行为。
对不起,这是什么意思?我提到它只在使用
多重继承时才会失败。然后,如果它是一个未定义的行为,为什么它使用单继承时完美无缺?
Disregarding compiler-specific behavior there are only two things
you can do with a void* pointer casted from a type T: compare it wrt.
equality to another such void* pointer, and cast it back to T.
You cast to void* from a type X and then cast back to Y, and that''s
Undefined Behavior even if the types X and Y are related.
I''m sorry but what does this mean? I mentioned that it only fails when
multiple inheritance is used. Then if it''s an undefined behavior, why does
it work flawlessly, when single inheritance is used?




未定义行为意味着效果可以是任何东西,包括你在内的任何内容...... b $ b认为它应该是。


不要依赖未定义的行为。



Undefined Behavior means the effect can be anything, including whatever you
think it "should" be.

Don''t rely on Undefined Behavior.

考虑:

struct A {int x;结构B {int y;结构X:A,B {};

X * pX =新X;
A * pA = static_cast< A *>(pX);
B * pB = static_cast< B *>(pX);

''pA''指向A子对象的开头,''pB''指向
B子对象的开头;这两个指针不能相等。
Consider:

struct A { int x; };
struct B { int y; }
struct X: A, B {};

X* pX = new X;
A* pA = static_cast<A*>( pX );
B* pB = static_cast<B*>( pX );

''pA'' points to the beginning of the A subobject, and ''pB'' points to
the beginning of the B subobject; these two pointers cannot be equal.



我明白你的意思但这不是我想要的。

在我的第一篇文章中考虑案例1,它与IInterface一起工作。类型
指针上的定义,



I got your point but this isn''t what exactly I wanted.

Consider case 1 in my first post, it worked with the "IInterface" type
definition on the pointer,




案例1:

IInterface * pInterface = new CImplementation();

pInterface->方法();


案例2


案例2:

无效* pInterface = static_cast< void *>(new CImplementation());

static_cast< IInterface *>(pInterface) - >方法();


失败,因为指针重新构建期间发生了一些不好的事情。


不,它失败了,因为它可以。它_can_失败因为它是UB。但是,

如果您投射的类型与您投射的类型相同'不再是
UB并且不会失败:


void * pInterface = static_cast< IInterface *>(new CImplementation());

static_cast< IInterface *>(pInterface) - > Method();


不是我推荐这样的东西。


不要使用void *。


我之所以尝试使用void *是因为我不能在这种特殊情况下存储类型定义。


如果你可以将指针从void *转回来,那么你知道类型和

首先不必使用void * 。


简单。


在第一行
中,类分配器不知道它应该使用什么类型。





关于指针本身。指针只是一个地址吗?


一般没有,但对于大多数指针,是的。


无效*能够存储任何类型的指针?


不,但是它能够存储你在这里使用的那种。


如果是这样,为什么赢了''铸造工作?



Case 1:
IInterface *pInterface = new CImplementation();
pInterface->Method();

case 2
Case 2:
void* pInterface = static_cast<void*>(new CImplementation());
static_cast<IInterface*>(pInterface)->Method();

fails because something bad happened during pointer re-casting.
Nope, it fails because it can. It _can_ fail because it''s UB. However,
if the type you cast from is the as same the one you cast to it''s no longer
UB and won''t fail:

void* pInterface = static_cast<IInterface*>( new CImplementation() );
static_cast<IInterface*>( pInterface )->Method();

Not that I recommend such things.

Don''t use void*.

The reason why I''m trying to use void* is because
I can''t store the type definition in this particular case.
If you can cast the pointer back from void*, then you know the type and
don''t have to use void* in the first place.

Simple.

In the first
line, the class allocator has no idea about what type should it use.
?

Regarding the pointer itself. Isn''t the pointer just an address?
In general no, but for most pointers, yes.

Isn''t void* capable of storing any kind of pointers?
No, but it''s capable of storing the kind you''re using here.

If so, why won''t casting work?




因为你是从X型铸造而回到不同的Y型。


-

答:因为它弄乱了人们通常阅读文字的顺序。

问:为什么这么糟糕?

A:热门发布。

问:usenet和电子邮件中最烦人的事情是什么?



Because you''re casting from a type X and back to a different type Y.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?


这篇关于投射到无效*,结果出乎意料。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆