4

我只是在读 Stroustrup 的新书。在第 22.2.2 章中,他讨论了一个 dynamic_cast 问题。

我自己编写的测试代码如下:

class Storable  
{
public:
    int i;
    virtual void r() {};
    Storable()  
    {
        i = 1;
    };
};

class Component:public virtual Storable
{
public:
    Component()  
    {
        i = 1;
    };
};

class Receiver:public Component
{
public:
    Receiver()  
    {
        i = 2;
    };
};

class Transmitter:public Component
{
public:
    Transmitter()  
    {
        i = 3;
    };
};

class Radio:public Transmitter
{
public:
    Radio()  
    {
        i = 4;
    };
};


int _tmain(int argc, _TCHAR* argv[])
{
    Radio *r = new Radio();
    Storable *s1 = dynamic_cast<Storable*>(r);

    Component *c = dynamic_cast<Component*>(s1);  // this should be 0 but it is not!

    return 0;
}

Stroostrup 解释说 c 应该是一个 nullptr 因为不可能知道哪个版本的 Storable 被引用。但是,我认为它是一个有效的指针。

我猜想 Stroustrup 在这点上可能是正确的,但我看不出我巧妙地错过了什么,其他人能发现吗?

4

1 回答 1

3

我看不出那里有歧义。您是否正确转录了示例?引用 C++11, [expr.dynamic.cast]§8(使用dynamic_cast<C*>(v)):

...如果v指向(引用)最派生对象的公共基类子对象,并且最派生对象的类型具有类型为 的基类,该基类C是明确的并且public,则结果指向(引用)C子对象派生最多的对象。

v的 is s1,它指向Storable一个最派生的类型对象的子对象Radio。只有一个 in 类型Component的基类子对象Radio,它是公共的,所以动态转换应该成功,就像它一样。

如果Radio也来自于,那将是模棱两可Receiver的;也许你错过了?

于 2013-09-30T09:58:19.847 回答