类Dog
和Cat
派生自Animal
,而又派生自Creature
。此外,pDog
、pCat
、pAnimal
和pCreature
都是指向他们类的指针。 Animal
和Creature
都是抽象类。
我的代码有什么问题?
pAnimal = new Dog();
pDog = pAnimal;
您可以隐式地向上转换层次结构(即从派生到基(。
向下转换层次结构(从基础到派生(必须显式完成。在大多数情况下,您希望使用dynamic_cast
以便转换只有在正确的情况下才会成功:
Animal *pAnimal = new Dog();
Dog *pDog = dynamic_cast<Dog *>(pAnimal);
请注意,您的类需要至少包含一个虚函数才能正常工作(但如果您没有虚函数,则层次结构可能根本没有意义(。
我假设pAnimal
是Animal*
类型,pDog
是Dog*
类型。
当你将new Dog()
分配给pAnimal
时,它会将Dog*
转换为完全合法的Animal*
,因为Dog
派生自Animal
。
然而,以另一种方式返回(即从Animal*
到Dog*
的铸造(是不同的。由于在某些情况下,这将是一个无效的强制转换(即,如果pAnimal
指向Cat
(,编译器要求您显式强制转换它,例如:
pDog = static_cast<Dog*>(pAnimal);
如果您不确定类型,则需要使用 dynamic_cast
,例如:
pDog = dynamic_cast<Dog*>(pAnimal);
if (!pDog)
{
// invalid cast, pAnimal didn't point to a Dog
}
dynamic_cast
将检查强制转换是否有效,如果无效,它将返回一个空指针。
编辑:使用static_cast
可能会比dynamic_cast
略微提高性能,但是只有在您110%确定该类型时才应使用。
您希望编译器记住Dog
始终是代码中指向的类型。
通常,您不能将任何旧Animal *
分配给Dog *
。
在您的特定情况下,C++将遵循相同的一般规则。 编译器不会扫描您的代码以查看是否允许pDog = pAnimal;
。
猜测pAnimal
是Animal*
的,pDog
是Dog*
的,那么你有一个类型不匹配,这是由于Animal*
不能从对象的动态类型独立地转换为Dog*
。
您可以:
- 通过
static_cast
向下投射,如果您确定指向的对象的动态类型 - 如果您不确定,请通过
dynamic_cast
向下投掷