2010-04-10 103 views
13

我一直在读的StackOverflow太多,开始怀疑所有我曾经写过,我一直在想代码“那是未定义水煤浆?”即使在代码已经工作了很长时间。铸造指针对象为void *在C++

所以我的问题 - 它是安全和定义良好的行为将一个指向对象(在这种情况下,抽象接口类)转换为void *,然后将它们转换回原始类并调用使用它们的方法?

我充分认识到执行此代码可能是可怕的。我甚至不会考虑现在这样写(这是旧的代码,我不想改变),所以我不想讨论更好的方法来做到这一点。如果我再次这样做,我已经知道如何写得更好。但是,如果实际上在C++中依赖于此,那么我将不得不考虑更改代码,如果它只是非常糟糕的代码,那么更改它就不是优先级。

我不会有任何有关的东西怀疑这个简单的一两年以前,但作为我的C++的增加其实我觉得了解我对代码越来越多的担忧是在标准的安全,即使它工作得很好。也许读太多堆栈溢出是因为有时候生产力坏事:P

回答

16

你是安全的。

从C++(0X)草案,

§ 5.2.9/13(对于static_cast):

类型的指针的值,以对象转换为“指针CVvoid”和可能具有不同的简历资格,应具有其原始价值。

§ 5.2.10/7(用于reinterpret_cast):

转换类型的右值“指针T1”的类型“指针T2”(其中T1T2是对象类型和其中的T2的对准要求并不比的T1严格)和返回到其原始类型产生的原始指针值。

(当然,铸造到一个不相关的类是未定义的行为。)

+1

虽然这种行为在C++ 0x中当然没有变化,但我认为从不接受草案标准的草案引用来回答关于语言当前状态的问题是不好的做法。 – 2010-04-10 14:27:13

+0

谢谢。在C++编程十年之后,我觉得这样的基本问题很愚蠢,但我对C++的了解越多,我越是怀疑自己。其他人有这种感觉吗? ...嗯,那就是我。 – jcoder 2010-04-11 10:40:44

8

所以我的问题 - 它是安全的和明确的水煤浆投一个指向对象(在这种情况下,抽象接口类)为void *然后再将它们转换回原始类并使用它们调用方法?

是 - 只要你施放回完全相同类型。否则,基类指针调整可能会破坏指针的值。

在实践中,这一点使用多重继承时是(可能)唯一相关:指针派生类可以在它们的物理地址不同的指针从它们的基类。

1

我们使用这种技术通常以避免在根据您所使用的环境中的每个单独的类switch语句(基于Web,Windows和Linux等)

使用void **的引用。

void ** detailObject; 

创建函数返回引用的对象:

TheObject *TheClass::GetObject(){ 
    TheObject *object = (TheObject*)object; 
    return object; 
} 

只需使用函数作为对象从现在开始。例如GetObject()->Go();