为啥C ++允许将指向基对象的指针转换为派生类的指针[重复]

Posted

技术标签:

【中文标题】为啥C ++允许将指向基对象的指针转换为派生类的指针[重复]【英文标题】:Why C++ allow converting pointer to base object into pointer of derived class [duplicate]为什么C ++允许将指向基对象的指针转换为派生类的指针[重复] 【发布时间】:2012-11-21 03:43:10 【问题描述】:

可能重复:Downcasting using the Static_cast in C++

我很困惑什么时候需要将指向基对象的指针转换为派生类的指针? 谁能帮我举个例子?

【问题讨论】:

【参考方案1】:

你说的是哪种转化

如果是关于向下转换(或动态转换,它是同一类型,但在运行时验证),那么你可以这样做来强制类型检查器不通过强制执行您指定的类型来检查该特定类型。

这意味着它是代码内部的潜在中断,该特定指令中缺少保证的类型安全,但有时需要它,即使一个好的设计不应该先验地需要它。

必要性是因为如果没有强制转换,即使您确定指向基类的指针包含派生类,您也不能调用派生类的任何方法(但编译器可以' t 验证它)。

【讨论】:

【参考方案2】:

何时

这里有一个例子:

假设您有一个工厂(动物工厂),您可以向它发送一个字符串或您想要的对象类型的枚举...

“嘿,动物工厂,给我一条‘狗’”

有两种方法可以编写你的工厂...

您可以像这样为每一种动物编写一个函数(优秀的程序员不会这样做):

狗* GetDog(); Cat* GetCat(); 等

或者你可以用这样的一个函数编写一个工厂(暂时不要考虑泛型):

Animal* GetAnimal(string animalType);

您知道 Animal 实际上是一只狗或猫,因此您可以将其类型转换为您需要的类型您需要访问 Dog 或 Cat 的成员...

我最喜欢在 C++ 中做的事情是临时转换来做某事 (请原谅我的 C++ 生锈了)

Animal* myAnimal = Factory.GetAnimal("Dog");
int barkVolume = ((Dog*)myAnimal).BarkVolume;

【讨论】:

【参考方案3】:

假设您有一个基类Animal 和两个派生类CatDog

// Assume methods are public.
class Animal  virtual void Attack(); 
class Dog : public Animal  void Meow(); 
class Cat : public Animal  void Bark(); 

我们可以使用基类指针来引用我们的派生对象。这很有帮助,因为我们现在可以将它们包含为相同的类型。

Animal* myCat = new Cat;
Animal* myDog = newDog;
std::vector<Animal*> myAnimals;
myAnimals.push_back(myCat);
myAnimals.push_back(myDog);

这很有用,因为我们可以调用所有种类的动物的基成员函数,而不管它们的派生类类型如何。

// Call Attack() on every cat and dog.
for_each(myAnimals.begin(), myAnimals.end(), [](auto& e)  e->Attack(); );

您可以使用动态转换来测试是否可以将基指针之一转换为派生类指针。

Cat* realCat = dynamic_cast<Cat*> myAnimals[0]; // Success. Pointer is valid.
Cat* fakeCat = dynamic_cast<Cat*> myAnimals[1]; // Failure, it's not a cat. NULL.

您现在可以从派生类指针调用您的成员方法,例如Meow()。这在以前是不可能的,因为Animal 没有这些方法。

realCat->Meow(); // Valid.
myCat->Meow(); // Animal*, there is not Meow() method.

【讨论】:

【参考方案4】:

您需要这样做才能访问基类中不存在的派生类成员。但是,有了良好的编程实践和泛型,您可能不应该将指针类型化为基类。

【讨论】:

以上是关于为啥C ++允许将指向基对象的指针转换为派生类的指针[重复]的主要内容,如果未能解决你的问题,请参考以下文章

类型兼容---子类的对象可以给父类指针赋值

重新解释适当对齐的指向具有声明类型的对象的指针

将c ++引用的地址传递给指针

将基类转换为派生类[重复]

面向对象编程感悟

typeid详解