请考虑以下代码:
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 *”的rvalue的“b *”类型的变量 我写的时候工作正常
a *instance = new b();
输出结果为:
foo1
foo2
有人可以解释一下原因吗?我将非常感激:))
另一件事,如果我写
instance->~a();
以上return 0;
没有额外的事情发生。这是因为构造函数只能被调用一次吗?
答案 0 :(得分:6)
b
是a
a
不是b
。
您可以将Giraffe
类型的实例放入Animal
类型的变量中
但是,您无法将Animal
的实例放入Giraffe
类型的变量中(如果它是Porcupine
会怎么样?)
答案 1 :(得分:4)
根据定义,派生类可以做基类可以做的超集。派生类可以执行基类可以执行的所有操作,但反之亦然。因此,将派生类视为基类是有意义的,反之亦然。例如:
class Animal {
void eat();
};
class Dog : public Animal {
void bark();
}
将Dog
视为通用Animal
非常有意义,但如果订购到Animal
,通用bark
就没有合理的理由。
答案 2 :(得分:4)
让我们更具体一点:
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()
创建的内容可以是任何类型的动物。将它分配给Bat
的变量可能无效,因为它可能不是蝙蝠。
答案 3 :(得分:1)
由于a
不是b
,因此您无法将指向b
的指针指定给a
类型的对象。
由于b
是一个a
,所以它确实可以正常工作。
答案 4 :(得分:1)
b
是一种a
。但是,a
不是b
的类型。如果b
包含其他成员,那么当b
真正引用a
类型的对象时,如果您尝试访问它们会发生什么。
这不是一个安全的演员。
答案 5 :(得分:1)
始终记住这一点,您不能将基类对象分配给派生类指针。 [派生类对象]是[基类对象]。 反之则不然。
答案 6 :(得分:0)
问题在于“是一种”关系。 class a
的对象不是class b
的对象
b *instance = new a(); // won't work
意味着您尝试将指针class b
设置为不是对象class b
的内容。与此同时,你可以做相反的事情:
a* instance = new b(); //will work
因为class b
的对象也是class a
的对象,所以在这里你要设置指向class a
的指针到确实是class a
的对象的东西。
答案 7 :(得分:0)
您无法用a
替换b
,因为a
没有b
的所有功能。因此,做出这样的任务毫无意义。
对于你的第二部分,99%的时间你说delete var
要销毁用new
分配的东西,而不是明确地调用析构函数,这是一个高级主题。
答案 8 :(得分:0)
关于析构函数 -
如果操作数的静态类型与动态类型不同,那么它的静态类型表现为基类,它的析构函数必须是虚拟的。
此外,派生类的指针/引用与基类的指针/引用类型兼容。但其他情况并非如此。 (没有传递性质)
在你的情况下 -
a *instance = new b(); // This should be correct way.
instance
的静态类型为a*
,而动态类型为b*
。因此,a
充当基类,它的析构函数必须是虚拟。