我试图弄清楚多态性和指针,并关注一些解释它的精彩视频(hyperlink if you really care)
他声明class A
和class B
继承自A。
但是要实例化B的对象,他这样做是这样的:
A* b = new B;
,并且效果很好(他在创建更复杂的类时继续使用该方法,即基类型为Shape的向量数组,其中包含子类Square,Circle等。
std::vector<Shape*> shapes;
shapes.push_back(new Circle.........
shapes.push_back(new Rectangle.......
有可能,但声明一个指向基类对象的指针,然后通过指向其子类实例化该指针完全正常(甚至推荐)吗?
我想我刚刚回答了我自己的问题,即好处是能够通过按父类引用不同对象来管理它们呢?正确吗?
谢谢!
答案 0 :(得分:1)
但是,声明一个指向基类对象的指针,然后通过指向其子类实例化该指针,是否完全可以(甚至推荐)?
使用时
A* ptr = new B();
代替
B* ptr = new B();
您正在丢失的信息很少。您不能使用B
中定义的任何成员函数,而不能使用A
中定义的成员函数。请注意,最好使用在virtual
中声明但在A
中实现的B
成员函数。
如果在您的用例中可以做到那一点点损失,那么使用A* ptr =
没有任何危害。如果您希望保留指针的B
性质,以便可以使用它来访问特定于B
的成员,则必须使用B* ptr =
。
有关使用指针/引用类型的指导原则:
在定义函数接口时,请使用在类层次结构中尽可能高级的指针/ referene类型来实现函数。
给予
struct Shape { ... };
struct Circle : Shape { ... };
如果可以从Circle
获得函数中需要的所有内容,请不要在函数的界面中使用Shape
。
添加Shape
的下一个子类时,
struct Rectangle : Shape { ... };
该功能也可以与Rectangle
一起使用,而无需进行任何更改。
在定义指针/引用时,请使用保留尽可能多的信息的类型。
如果有功能
Circle* someFunction();
然后使用
Circle* circlePtr = someFunction();
代替
Shape* shapePtr = someFunction();
您可以在需要circlePtr
的任何地方使用Shape*
,但是在需要shapePtr
的任何地方都不能使用Circle*
。
答案 1 :(得分:1)
您部分回答了您的问题,但是还有其他原因。
多态性使您可以使某些事物保持抽象。例如,想象一下这样的代码:
Person *actor;
if (occupation == 'nerd') {
actor = new NerdPerson();
}
else if (occupation == 'mortician') {
actor = new MorticianPerson();
}
...
actor->printOccupation();
显然,这是一个虚假的原因。因此,可能与某物的收藏有关,但这只是一个原因。