问题2:是否只有通过基类指针或引用间接指向派生类子类型时,多态性才会起作用?
等级:初级
只有通过基类指针或引用间接指向派生类子类型时,多态性才会起作用。使用基类对象并不会保留派生类的类型身份,不再具备多态性。
深入讨论:
这个问题和答案有一点模糊,让我们通过一个示例来明确这个问题。
#include <iostream>
class Base {
public:
virtual void f() {
std::cout<< “Calling Base::f()…\n”;
};
};
class Derived: public Base {
public:
virtual void f() {
std::cout<< “Calling Derived::f()…\n”;
};
};
|
类Base和Derived,Derived从Base继承而来,子类Derived覆盖(Override)了基类Base中定义的虚函数f()。如果通过基类对象指针或引用来调用虚函数f(),那么会调用类对象的动态类型中所定义的函数,多态性发挥了作用。所以,如果执行如下代码:
Base* pb = new Base();
Base* pd = new Derived();
pb->f();
pd->f();
Base& rb = *pb;
Base& rd = *pd;
rb.f();
rd.f();
|
会得到如下结果。
Calling Base::f()...
Calling Derived::f()...
Calling Base::f()...
Calling Derived::f()...
|
如果通过基类对象来调用虚函数f(),基类对象并不会保留派生类的类型身份,不再具备多态性。所以,如果执行如下代码:
Derived d;
Base b = d; // d被“切割”成一个Base对象
d.f();
|
会得到如下结果。
尽管用d初始化b是合法的,但是b不再是一个Derived对象。在初始化b之前,d的Derived部分被切除,成为了一个Base对象。所以,最后调用了方法Base::f()。这也是C++被人广为诟病的特性之一,作为一种面向对象编程语言,我们必须使用指针以引用而不是对象来支持面向对象程序设计。
可能有一些善于思考的读者会想到一种情况:如果基类对象通过解引用操作符*获得,调用虚函数是否具备多态性?例如,执行如下代码会得到什么结果:
Base* pb = new Base();
Base* pd = new Derived();
Base b = *pd;
b.f();
(*pd).f();
|
执行结果如下:
Calling Base::f()...
Calling Derived::f()...
|
为什么(*pd).f()会调用Derived::f()?因为通过解引用操作符*获得不是一个基类Base对象,而是子类Derived对象。
参考资料:
《C++ Primer》第四版章节17.5导言部分。
《Inside C++ Object Model》章节1.3。
分享到:
相关推荐
这样,当使用基类指针调用这个函数时,实际执行的是派生类中的版本,这就是多态性(polymorphism)的体现。 ```cpp class BaseClass { public: virtual void draw() { /* 基类实现 */ } }; class DerivedClass : ...
9. **虚函数**:虚函数允许基类指针或引用调用派生类的相应重写函数,实现多态性。虚函数在基类中用`virtual`关键字声明,并在派生类中可以重定义。 10. **纯虚函数与抽象类**:纯虚函数是在基类中声明但没有实现的...
虚函数(Virtual Function)是实现多态的关键,它允许我们通过基类指针或引用调用派生类的成员函数,即使该指针或引用实际指向的是派生类的对象。这样,即使基类指针指向了派生类对象,也能调用派生类中重写过的虚...
派生类中虚函数的声明必须与基类保持一致,除非返回类型涉及到多态引用或指针,这时派生类的虚函数可以返回基类函数所返回类型的派生类引用或指针。 在面向对象设计中,多态性使得我们可以设计出更加灵活的代码。...
8. 虚函数与多态性,多态性通过虚函数实现,虚函数允许派生类覆盖基类中的方法,使得基于基类类型的指针或引用能够调用派生类的方法。 在具体的学习中,应该注意以下几点: - 类的继承是实现代码复用的手段,但更...
在 C++ 中,公有派生类就是基类的子类型,能够实现多态性,使得基类指针或引用可以指向派生类对象,从而在不修改原有代码的情况下增加新功能或改进现有功能。 4. 多态性与虚函数: 多态性是面向对象编程的重要特性...
- **公有继承(Public Inheritance)**:派生类能够访问基类的所有公有和保护成员,这使得派生类成为基类的子类型,允许使用基类的指针或引用指向派生类的对象。 - **保护继承(Protected Inheritance)**:只允许...
- 当使用基类指针指向派生类对象时,C++编译器会在运行时查找实际的对象类型,并调用相应的函数版本。这一过程被称为“动态绑定”。 - 如果没有使用 `virtual` 关键字声明虚函数,则调用的将是基类的版本,这称为...
在C++编程语言中,指针和引用是两种非常重要的概念,它们经常被用来处理对象间的交互,尤其是在涉及多态性(polymorphism)时,如虚函数的应用。本实例“使用指针和引用处理虚函数实例”着重探讨了如何通过这两种...
- 间接继承使得多态性成为可能,基类指针或引用可以指向其派生类的对象,从而实现动态绑定和运行时类型识别。 9. **继承与封装**: - 继承可以看作是封装的一种形式,它将基类的特性封装到派生类中,同时也允许...
在C++编程语言中,【第五次作业2】涉及到的核心概念包括了类的继承、多态性、抽象类以及输入/输出流。首先,我们来深入理解这些关键知识点。 1. **继承与类型转换**: - **基类与派生类**:C++中的继承允许一个类...
- 通过使用虚函数(virtual functions)和动态类型(dynamic type),可以实现运行时的多态性,允许通过基类指针或引用调用派生类重写的成员函数。 这些规则使得C++中的继承体系具备了强大的灵活性和扩展性,允许...
总的来说,虚函数表是C++实现多态性的一种关键机制,它允许我们通过基类指针调用派生类的成员函数,从而实现运行时的类型检查和动态绑定。理解虚函数表的工作原理对于编写高效且可维护的C++代码至关重要。
通过声明基类指针或引用指向派生类对象,并通过这些指针或引用来调用方法,实现运行时的多态。 8. 封装(Encapsulation): 多态性通常与封装一起工作。封装是指隐藏对象的内部状态和实现细节,仅对外公开有限的...
虚函数在多态性中起着关键作用,尤其是在使用基类指针或引用调用成员函数时。 - **虚析构函数**:对于含有动态分配资源的类,应声明虚析构函数,确保在删除派生类对象时正确调用派生类的析构函数,防止内存泄漏。 ...
- 虚函数(Virtual Function)是基类声明的,允许在派生类中重写的行为,是多态性的重要实现方式,可以被派生类继承。 7. 友元函数: - 友元函数(Friend Function)不属于类的成员,但可以访问类的私有和保护...
3. **派生类的指针可以隐含转换为基类的指针**:这种转换在多态编程中尤为关键,因为它允许我们通过基类指针调用派生类中重写的虚函数,实现运行时的多态性。需要注意的是,如果基类指针调用非虚函数,那么实际执行...
描述中提到的“隐式转换”是指当一个派生类对象的指针或引用被用作基类指针或引用时,编译器会自动进行这种转换。这种转换是安全的,因为派生类是基类的子类型,所以派生类对象可以被视为基类对象。例如,如果`...
- 但是基类的指针或引用可以指向或引用派生类的对象,而派生类的指针或引用不能指向基类的对象,这是向下转型的一个限制。 6. 构造函数与析构函数: - 在类层次中,基类的构造函数会被自动调用来初始化继承的成员...
这在多态性中尤为重要,因为派生类的对象可以被视为基类的对象,使得基类的指针或引用可以调用派生类的重载函数,从而表现出多态性。 接下来,我们要注意的是函数重载的一些规则和注意事项。C++中,函数的返回类型...