向上投射不透明指针



我正在尝试使用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会正常工作吗?在这种情况下可以使用其他类型的石膏吗?

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

n5.2.7.2 的 n3242(我知道这不是官方标准,但它应该很接近)说关于 dynamic_cast(v),

如果 T 是指针类型,则 v 应是指向完整类类型的指针的 prvalue,结果是 T 类型的 prvalue。如果 T 是左值引用类型,则 v 应是完整类类型的左值,结果是 T 引用的类型的左值。如果 T 是右值引用类型,则 v 应是具有完整类类型的表达式,结果是 T 引用的类型的 x值。

所以dynamic_cast不起作用。

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

5.2.10.7说关于reinterpret_cast(v),

指向

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

所以reinterpret_cast可能会起作用。

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

如果我没记错的话,你根本不需要任何显式强制转换,因为SomeInterface_PublicClass_impl的基类,你总是可以隐式转换为基类。

我实际上尝试在没有 GCC (4.5.1) dynamic_cast的情况下编译您的代码,并且确实没有错误或警告(我SomeInterface定义为空类)。

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

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

如果基类

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

如果出于某种原因您想使用显式强制转换,那么简单的静态强制转换应该没问题:

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

最新更新