使用超类的实例覆盖子类的实例

时间:2014-08-19 08:50:28

标签: c++ types casting

试图解决问题(实际上是在Ada中)我想出了以下代码。为什么合法?

class Superclass {
public:
    virtual void Announce() {
        printf("I am the superclass\n");
    }
};

class Subclass : public Superclass {
public:
    void Announce() {
        printf("I am the subclass\n");
    }
};

int main() {
    Superclass osuper;
    Subclass osub;

    Superclass* p = &osub;
    *p = osuper;
    osub.Announce();

    return 0;
}

main()中,我创建了Subclass的实例,然后使用Superclass的实例对其进行物理覆盖。然后,我成功地在覆盖(以及如此损坏的)对象上调用了Subclass的方法。

我无法直接指定osub = osuper,因为这没有任何意义,但通过指针我似乎绕过了它。上面的代码编译得很好,没有任何警告,但是当我调用osub.Announce()时,osub内的内存不再包含有效的Subclass对象。

这可能是类型安全的(甚至,通常是安全的),但编译器似乎非常高兴。为什么呢?

5 个答案:

答案 0 :(得分:6)

在对象上使用=运算符无效,并且它不会覆盖任何内容,将使用默认的复制构造函数。 如果你想真正覆盖内存中的对象,请尝试memcpy(p,& osub,sizeof(Superclass))。现在这将是一个覆盖:)

请参阅http://www.cplusplus.com/articles/y8hv0pDG/

答案 1 :(得分:2)

您正在调用复制赋值运算符,而不是“物理覆盖”。这个函数与构造函数之外的任何其他函数一样,可以修改已经存在的对象的成员,它不是“魔法”。

您的对象没有成员变量,因此隐式生成的operator=调用是无操作。没有“腐败的对象”。 osub.Announce();致电Subclass::Announce,因为osubSubclass

调用的实际函数是Superclass::operator=(Superclass const &);

函数Subclass::operator=(Subclass const &);在重载决策中失败,因为osuper不会隐式转换为Subclass const &

你可能会得到的是,如果Subclass有成员变量,那么行*p = osuper;可能会使osub对象处于Subclass设计者不想要的状态。

答案 2 :(得分:1)

需要很奇怪。 当调用子类实例的构造函数时,超类的构造函数将被调用到init成员变量。 但是,如果你想要这个,你可以实现这样的成员函数:

Subclass& copy(const Superclass& superobject);

答案 3 :(得分:0)

您应该在子类中放置一个返回超类的方法。     SuperClass getSuperClass(){         SuperClass sup;         //复制内容;     返回;     }

答案 4 :(得分:0)

这个工作原理的执行摘要似乎是:隐式复制构造函数讨厌你,并想伤害你。

隐式复制构造函数看起来像,就像它执行对象的逐字节复制一样,从而使得assign-to对象与assign-from对象相同。但是,它并没有这样做。它只是复制成员。它特别不会复制对象的vtable指针。分配可能会遇到同样的问题(虽然我还没有检查过这个问题)。我对C ++ 11的移动一无所知。

如果这违反了您的任何一个级别的合同,或者以任何其他方式对您的类层次结构没有任何意义,那么它基本上很难成为您。

这个故事的寓意是:课程应该始终从boost::noncopyable继承。

(我知道复制构造函数是从C开始的。这不是一个借口。)