C++ 向上投射不透明指针

C++ 向上投射不透明指针,c++,casting,opaque-pointers,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_clas

我想用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 ... */
     }
};
//some\u other\u class.h
类SomeOther类:私有公共类
{
使某些函数无效()
{
//_PublicClass_impl的定义未知
//因此,_impl是不透明的
SomeInterface*interface=dynamic_cast(_impl);/??
/*更多代码*/
}
};

在这种情况下,dynamic_cast可以正常工作吗?在这种情况下还有其他类型的强制转换吗?

如果我没有弄错的话,您根本不需要任何显式强制转换,因为
SomeInterface
\u PublicClass\u impl
的基类,您可以始终隐式强制转换到基类

实际上,我在没有GCC(4.5.1)中的
dynamic\u cast
的情况下编译了您的代码,并且确实没有错误或警告(我将
SomeInterface
定义为空类)

然而,有一个相关的问题引起了我的兴趣:为什么编译器会考虑到
SomeInterface
确实是
\u PublicClass\u impl
的基类,尽管后者在这个问题上是不透明的

我最近发现的一个解释是〈C++〉第5条第11.2条:

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

如果出于某种原因,您希望使用显式强制转换但是,简单的静态强制转换应该可以:

SomeInterface *interface = static_cast<SomeInterface *>(_impl);
SomeInterface*interface=static\u cast(\u impl);

据我所知,没有一种可行的方法来做你想做的事。reinterpret_cast或c样式cast可能可以工作(行为未指定),但当它允许您编译时,其他行为都是未定义的行为

n3242的5.2.7.2(我知道这不是官方标准,但应该很接近)中提到了dynamic_cast(v)

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

所以动态的演员阵容不起作用

静态_cast不起作用,因为在这两种类型之间没有定义任何有效的转换

5.2.10.7关于重新解释铸件(v)

指向对象的指针可以显式转换为指向不同对象类型的指针。69当类型为“指向T1的指针”的PRV值转换为类型为“指向cv T2的指针”时,如果T1和T2都是标准布局类型(3.9),则结果为静态_转换(静态_转换(v))T2的对准要求并不比T1严格。将“指针指向T1”类型的PR值转换为“指针指向T2”类型(其中T1和T2是对象类型,T2的对齐要求不比T1严格),然后返回到其原始类型,即可生成原始指针值。未指定任何其他此类指针转换的结果

因此,重新解读演员阵容可能会奏效


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

Hmm,因此编译器会理解
\u PublicClass\u impl
扩展了
SomeInterface
,即使定义在特定的编译块中不可见?它需要显式强制转换。我的实际代码中出现错误:
sftp.cpp:26:错误:无法在初始化中将'sshfm::net::ssh::\u ssh\u impl*const'转换为'sshfm::util::wrapper*'。
<代码>\u ssh\u impl确实实现了后一个类,但在编译时它是未知的,因为它的声明不可见。我选择使用中间接口,因为我只需要访问封装数据的一部分。我认为,
reinterpret\u cast
可能会起作用,因为RTTI会在运行时提供类型信息。reinterpret\u cast可能起作用的原因是,在不相关的指针类型之间进行强制转换时,它最有可能做的就是从派生类指针转换为基类指针时应该执行相同的操作。没有什么。只要在执行强制转换时不需要调整指针,它就应该可以工作。不寻常的实现可能有不同的规则。