C++ 以这些不同的方式声明继承类的实例是否有差异?
如果我有一个名为“Animal”的类和一个派生类“Bird:public Animal”,我可以通过以下两种方式创建一只鸟:C++ 以这些不同的方式声明继承类的实例是否有差异?,c++,C++,如果我有一个名为“Animal”的类和一个派生类“Bird:public Animal”,我可以通过以下两种方式创建一只鸟: Animal *sparrow = new Bird; Bird *sparrow = new Bird; 两者都编译得很好,并按预期工作。它们相等吗?我应该选择一个而不是另一个吗?这条线本身并没有显示出区别。但是,假设Bird声明了一个Fly方法,该方法在Animal上不存在。您将无法执行以下操作: Animal* a = new Bird; a->Fly();
Animal *sparrow = new Bird;
Bird *sparrow = new Bird;
两者都编译得很好,并按预期工作。它们相等吗?我应该选择一个而不是另一个吗?这条线本身并没有显示出区别。但是,假设
Bird
声明了一个Fly
方法,该方法在Animal
上不存在。您将无法执行以下操作:
Animal* a = new Bird;
a->Fly();
另一方面,这是合法的:
Bird* b = new Bird;
b->Fly();
这里的区别是C++是静态类型语言的结果。当编译器验证方法调用之类的事情时,它关心的是变量的静态类型。由于变量a
的静态类型是Animal
,它没有Fly
方法,编译器将不允许您对其调用Fly
(并非所有动物都能飞,因此您必须显式地将其转换为Bird
:动态_cast(a)->Fly()
是合法的)
表达式
newbird
的类型为Bird*
。如果将派生类型的值分配给基于类型的变量,编译器将不会抱怨(所有Bird
s都是Animal
s,因此它应该始终工作)。基本上,编译器将Bird*
上传到Animal*
。事实并非如此。并非所有的Animal
s都是Bird
s,因此您必须承担责任,明确地执行强制转换,并告诉编译器我知道该对象实际上是Bird*
。只有在这种情况下,编译器才允许您使用特定于Bird
的功能。因此,一般来说,如果需要使用特定于Bird
的成员,最好使用Bird*b=newbird代码>我想我明白了。一个在我脑海中清晰的后续行动:动物*A=新动物;动物*B=新鸟;有了这些声明,A和B之间有什么区别吗?(在上面的一些编辑之前提出的问题)@Jarred:是的,A
指向的对象实际上不是一只Bird
,而B
指向的对象实际上仍然是一只Bird
,你只是决定现在不在乎它是鸟(因为你的功能同样适用于所有动物,不依赖于鸟类的任何特定功能)。由于B
是一只Bird
,您可以再次成功将其向下转换为Bird*
,并使用Bird
特定成员。将a
转换为Bird*
将不会成功。非常感谢您提供的有用答案。