声明一个基类类型的指针,然后通过指向一个子类实例化它。这是良好的编程习惯吗?

时间:2019-04-11 21:01:33

标签: c++ polymorphism

我试图弄清楚多态性和指针,并关注一些解释它的精彩视频(hyperlink if you really care

他声明class Aclass B继承自A。

但是要实例化B的对象,他这样做是这样的:

A* b = new B;

,并且效果很好(他在创建更复杂的类时继续使用该方法,即基类型为Shape的向量数组,其中包含子类Square,Circle等。

std::vector<Shape*> shapes;
shapes.push_back(new Circle.........
shapes.push_back(new Rectangle.......

有可能,但声明一个指向基类对象的指针,然后通过指向其子类实例化该指针完全正常(甚至推荐)吗?

我想我刚刚回答了我自己的问题,即好处是能够通过按父类引用不同对象来管理它们呢?正确吗?

谢谢!

2 个答案:

答案 0 :(得分:1)

  

但是,声明一个指向基类对象的指针,然后通过指向其子类实例化该指针,是否完全可以(甚至推荐)?

使用时

A* ptr = new B();

代替

B* ptr = new B();

您正在丢失的信息很少。您不能使用B中定义的任何成员函数,而不能使用A中定义的成员函数。请注意,最好使用在virtual中声明但在A中实现的B成员函数。

如果在您的用例中可以做到那一点点损失,那么使用A* ptr =没有任何危害。如果您希望保留指针的B性质,以便可以使用它来访问特定于B的成员,则必须使用B* ptr =


有关使用指针/引用类型的指导原则:

  1. 在定义函数接口时,请使用在类层次结构中尽可能高级的指针/ referene类型来实现函数。

    给予

    struct Shape { ... };
    struct Circle : Shape { ... };
    

    如果可以从Circle获得函数中需要的所有内容,请不要在函数的界面中使用Shape

    添加Shape的下一个子类时,

    struct Rectangle : Shape { ... };
    

    该功能也可以与Rectangle一起使用,而无需进行任何更改。

  2. 在定义指针/引用时,请使用保留尽可能多的信息的类型。

    如果有功能

    Circle* someFunction();
    

    然后使用

    Circle* circlePtr = someFunction();
    

    代替

    Shape* shapePtr = someFunction();
    

    您可以在需要circlePtr的任何地方使用Shape*,但是在需要shapePtr的任何地方都不能使用Circle*

    < / li>

答案 1 :(得分:1)

您部分回答了您的问题,但是还有其他原因。

多态性使您可以使某些事物保持抽象。例如,想象一下这样的代码:

Person *actor;

if (occupation == 'nerd') {
    actor = new NerdPerson();
}
else if (occupation == 'mortician') {
    actor = new MorticianPerson();
}
...

actor->printOccupation();

显然,这是一个虚假的原因。因此,可能与某物的收藏有关,但这只是一个原因。