0

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

4

2 回答 2

1

如果我没记错的话,您根本不需要任何显式转换,因为SomeInterface它是 的基类_PublicClass_impl,并且您始终可以隐式转换为基类。

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

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

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

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

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

SomeInterface *interface = static_cast<SomeInterface *>(_impl);
于 2012-04-15T02:58:32.683 回答
1

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

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

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

所以 dynamic_cast 不起作用。

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

5.2.10.7 说关于 reinterpret_cast(v),

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

所以 reinterpret_cast 可能会起作用。

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

于 2012-04-15T03:44:39.850 回答