繁体   English   中英

为什么 C++ 不能用“超类”类型的右值初始化“派生类”类型的变量?

[英]Why C++ cannot initialize a variable of type “derived class” with an rvalue of type “super class”?

请考虑以下代码:

class a
{
    int a1;

    public:
    a()
    {
        printf("foo1\n");
    }
};

class b : public a
{
    int a2;
    public:
    b()
    {
        printf("foo2\n");
    }
};
int main (int argc, const char * argv[])
{
    b *instance = new a();
    return 0;
}

它给出了错误:无法用“a*”类型的右值初始化“b*”类型的变量当我写的时候工作正常

a *instance = new b();

output 是:

foo1
foo2

有人可以解释一下原因吗? 我将非常感激:)

另一件事,如果我写

instance->~a();

以上return 0; 没有额外的事情发生。 这是因为构造函数只能调用一次吗?

b是一个a
a不是b


您可以将Giraffe类型的实例放入Animal类型的变量中。
但是,您不能将Animal的实例放入Giraffe类型的变量中(如果它是Porcupine怎么办?)

根据定义,派生的 class 是可以做基础 class 可以做的超集的东西。 派生的 class 可以做基础 class 可以做的所有事情,但反之则不行。 因此,将派生的 class 视为基础 class 是有意义的,反之则不然。 例如:

class Animal {
    void eat();
};

class Dog : public Animal {
    void bark();
}

Dog视为通用Animal是完全有道理的,但如果命令通用Animal bark ,则没有任何合理的事情要做。

让我们更具体一点:

class Animal
{
    int a1;

    public:
    Animal()
    {
        printf("Animal\n");
    }
};

class Bat : public Animal
{
    int a2;
    public:
    Bat()
    {
        printf("bat\n");
    }
};
int main (int argc, const char * argv[])
{
    Bat *instance = new Animal();
    return 0;
}

你现在能明白为什么这可能无效了吗? 你用new Animal()创建的可以是任何类型的 Animal。 将其分配给Bat变量可能无效,因为它可能不是 bat。

由于a不是 a b ,因此您不能将指向b的指针分配给 a 类型a object 。

由于ba ,因此它确实可以正常工作。

b是 a 的a 但是, a不是b的类型。 如果b包含其他成员,那么当您尝试访问它们时会发生什么,如果b真的指的是 a 类型a object 。

这不是一个安全的演员。

请始终记住这一点,您不能将基本 class object 分配给派生的 class 指针。 [派生 class 对象] 是 [基础 class 对象]。 反过来是不正确的。

问题在于“是”关系。 Object 的class a不是 object 的class b所以

b *instance = new a(); // won't work

这意味着您尝试将指向class b的指针设置到不是 object class b的东西上。 同时你可以做相反的事情:

a* instance = new b(); //will work

since objects of class b are also objects of class a and so here you would set a pointer to class a onto something that is indeed an object of class a .

你不能用a代替 a b因为a没有b的所有功能。 因此,进行这样的分配是没有意义的。

对于你的第二部分,99% 的时间你说delete var来销毁用new分配的东西,而不是显式调用析构函数,这是一个高级主题。

关于析构函数 -

如果操作数的 static 类型与动态类型不同,则它的 static 类型表现为基础 class 并且它的析构函数必须是虚拟的。

此外,派生 class 的指针/引用与基本 class 的指针/引用类型兼容。 但其他情况并非如此。 (无传递性)

在你的情况下 -

a *instance = new b();  // This should be correct way.

static instance类型是a*而动态类型是b* 因此, a作为基础 class ,它的析构函数必须是virtual

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM