为什么我们需要一个超类的指针指向子类的对象?
Why do we need a pointer of superclass to point to a object of a subclass?
我现在正在学习c++,我读了很多关于使用超类的指针指向子类对象的材料,特别是在(纯)虚拟类的情况下。因为我没有太多的经验,有没有人能帮我理解为什么我们需要这样做?非常感谢!
你不需要。如果确实需要,可以使用指向派生类型的指针。
Liskov替换原则说,我们应该总是能够在期望基类型的地方使用派生类型。其思想是派生类型不应该比它的基类有更多的限制。这样,派生的实际上是一个基类型,并且可以在任何需要使用基类型的地方使用。基类型定义接口,派生类型应满足相同的接口。派生类型可以扩展接口,如果它喜欢的话。
函数应该接受的指针类型取决于您希望能够接受的类型。例如,如果您有两个Widget
, Button
和List
的层次结构,那么如果您的函数乐于接受任何类型的Widget
,它应该接受Widget*
。但是,如果函数特别需要Button
,则应该使用Button*
。这样做的原因是该函数可能需要一些只有Button
才能提供的功能。
当通过指针调用成员函数并且编译器看到该函数是virtual
时,编译器确保使用对象的动态类型来确定调用哪个函数。也就是说,假设您有一个Widget*
参数,但实际上传递了一个指向Button
对象的指针。对象的静态类型是Widget
(如果编译器只查看参数类型),但是它的动态类型是Button
。如果调用widget->draw()
,其中draw
是virtual
函数,它将看到动态类型是Button
,并确保调用Button::draw
。
但是,我一般不建议使用原始指针,所以如果可以的话,最好使用引用(Widget&
)或智能指针。
下面是一个例子:
struct base { virtual void do_stuff(); = 0 };
struct specialization1: base {
void do_stuff() override { std::cout << "doing concrete stuff"; }
};
假设你的客户端代码想要调用do_stuff。
第一个实现(这是不的方式):
void client_do_stuff( specialization1& s ) { s.do_stuff(); }
此函数有效。如果您决定(从现在起四个月后)添加代码库:
struct specialization2: base {
void do_stuff() override { std::cout << "doing other concrete stuff"; }
};
您可能希望为specialization2
的实例调用void client_do_stuff
。您可以使用专门化引用来复制client_do_stuff
,但这是代码复制,并且没有必要。
一个更好的解决方案是将client_do_stuff
更改为对基类的引用,并对两个特化使用相同的实现。
第二实施:
void client_do_stuff( base& b ) { b.do_stuff(); }
客户机代码:specialization1 s1;
specialization2 s2;
client_do_stuff(s1); // works
client_do_stuff(s2); // works
client_do_stuff的实现是根据基类的公共接口实现的,而不是专门化。这使得该函数"面向未来"(该原则有时被称为"面向接口编程,而不是面向实现")。
其思想如下:对象具有以下接口(纯虚类)。我将给你的代码提供一个具体的对象,它遵循这个接口,但是该对象的内部细节我将保留给自己(封装)。因此,你的代码不能对对象的精确大小等做任何假设。因此,在编译代码时,必须在操作对象时使用指针或引用。
- 通过指向指针数组的指针访问子类的属性
- 如何将子类作为函数的参数传递给期望基类,然后将该对象传递到指向这些抽象类对象的指针向量中?
- 将C++子类成员函数(虚拟实现)传递给 C 类型函数指针
- 为什么带有指针子对象的文字类类型的 constexpr 表达式不能是非类型模板参数
- 为什么使用父指针指向子类?
- C++通过基类指针提升子类的序列化
- 如果指针的子类的方法对于子类是唯一的,如何访问这些方法?
- C++基类指针调用子虚函数,为什么基类指针可以看到子类成员
- 为什么指向基类的指针可以指向子类的对象?
- C++ 使用正确的子类指针
- 如何在 BaseClass 指针数组中存储指向子类对象的指针?
- 带有基类指针的强制转换向量,指向子类
- 跨子类的共享指针
- 无法将参数 3 从 'const QGraphicsItem *' 转换为 'const QObject *',这是指针,对象是 QGraphicsObject 的子类
- 如何从其抽象母类上的指针初始化子类?
- 可以将指向子类的指针分配给Varibale的超级类型
- 声明基类类型的指针,但随后通过指向子类来实例化它.这是良好的编程实践吗?
- C++ - 如何使用基指针重写子类方法
- 指向子类对象的指针的静态数组出现问题
- Arduino:指针子类的继承和数组