向上转换不透明指针

时间:2012-04-15 01:47:14

标签: c++ casting opaque-pointers

我正在尝试使用pimpl成语。特别是,实现类将实现另一个接口:

// public_class.h
class PublicClass
{
public:
    /* public interfaces here */
private:
    class _PublicClass_impl;
    friend class _PublicClass_impl;
protected:
    _PublicClass_impl * const _impl;
};

// public_class.cpp
class PublicClass::_PublicClass_impl : public SomeInterface
{
    friend class PublicClass;
    /* all sort of stuff ... */
};

我的问题是,在下列情况下可以使用哪些演员阵容?

// some_other_class.h
class SomeOtherClass : private PublicClass
{
    void some_function()
    {
        // definition of _PublicClass_impl is unknown
        // thus, _impl is opaque

        SomeInterface * interface = dynamic_cast<SomeInterface *>(_impl); //??
        /* more code ... */
     }
};

在这种情况下,dynamic_cast会正常工作吗?在这种情况下是否可以使用任何其他类型的演员?

2 个答案:

答案 0 :(得分:1)

如果我没有弄错,根本不需要任何明确的演员,因为SomeInterface_PublicClass_impl的基类,你总是可以隐式演员到基类。

我实际上尝试在GCC(4.5.1)中编译代码而没有dynamic_cast ,确实没有错误或警告(我将SomeInterface定义为空类)。

但是,一个相关的问题引起了我的兴趣:为什么编译器会考虑SomeInterface确实是_PublicClass_impl的基类这一事实,尽管后者在所讨论的点上是不透明的? / p>

我最接近解释的是C ++标准第5条§11.2:

  

如果可以访问基类,则可以隐式地将指向派生类的指针转换为指向该基类的指针   class(4.10,4.11)。

如果由于某种原因你想要使用一个明确的演员,一个简单的静态演员应该没问题:

SomeInterface *interface = static_cast<SomeInterface *>(_impl);

答案 1 :(得分:1)

据我所知,没有一种可靠的方法来做你想做的事。 reinterpret_cast或c-style强制转换可能有效(行为未指定),但其他行为都是未定义的行为,当它允许你编译它时。

n4242的5.2.7.2(我知道它不是官方标准,但它应该是关闭的)关于dynamic_cast(v),

如果T是指针类型,则v应该是指向完成类类型的指针的prvalue,结果是类型T的prvalue。如果T是左值引用类型,则v应该是完整类的左值类型,结果是由T引用的类型的左值。如果T是右值引用类型,则v应该是具有完整类类型的表达式,并且结果是由T.引用的类型的xvalue。 / p>

所以dynamic_cast不起作用。

static_cast不起作用,因为两种类型之间没有定义任何有效的转换。

5.2.10.7说关于reinterpret_cast(v),

指向对象的指针可以显式转换为指向不同对象类型的指针.69当“指向T1的指针”类型的prvalue v转换为“指向cv T2的指针”类型时,结果为static_cast( static_cast(v))如果T1和T2都是标准布局类型(3.9)并且T2的对齐要求不比T1更严格。将“指向T1的指针”类型的prvalue转换为“指向T2的指针”类型(其中T1和T2是对象类型,T2的对齐要求不比T1更严格)并返回其原始类型会产生原始类型指针值。任何其他此类指针转换的结果都未指定。

所以reinterpret_cast可能会起作用。

最后,不使用强制转换不起作用,因为编译器不知道类型之间的关系。