c++多态

一、多态的基本概念

(1)基类指针只能调用基类的成员函数,不能调用派生类的成员函数;
(2)如果在基类的成员函数前加virtual关键字,把它声明为虚函数,基类指针就可以调用派生类的成员函数,通过派生类的成员函数,还可以访问派生对象的成员变量;
(3)有了虚函数,基类指针指向基类对象时就使用基类的成员函数,指向派生对象时,就使用派生类的成员函数,基类指针表现出了多种形态,这种现象称为多态;
(4)基类引用也可以使用多态。

注意:
(1)只需在基类的声明中加上virtual关键字,函数定义时不能加;
(2)在派生类中重定义虚函数时,函数特征要相同;
(3)当在基类中定义了虚函数时,如果派生类没有重定义该函数,那么将使用基类的虚函数;
(4)名字遮蔽和重载函数的规则也适用于虚函数;
(5)在派生类中重定义了虚函数的情况下,如果想使用基类的函数,可以加类名和域解析符;
(6)如果要在派生类中重新定义基类函数,则将它设置为虚函数,否则不要设置为虚函数;有两方面的好处,首先效率更高,其次指出不要重新定义该函数。

二、如何析构派生类

(1)构造函数不能继承,创建派生类对象时,先执行基类构造函数,再执行派生类构造函数;
(2)析构函数不能继承,而销毁派生类对象时,先执行派生类析构函数,再执行基类构造函数;
(3)派生类的析构函数在执行完后,会自动执行基类的析构函数;
(4)如果手动的调用派生类的析构函数,也会自动调用基类的析构函数。

析构派生类的要点如下:
(1)析构派生类对象时,会自动调用基类的析构函数。与析构函数不同的是,在派生类的析构函数中不用现实地调用基类的析构函数,因为每个类只有一个析构函数,编辑器知道如何选择,无需程序员干涉。
(2)析构函数可以手动调用,如果对象中有堆内存,析构函数中以下代码是必要的:

delete ptr;
ptr = nullptr;

(3)用基类指针指向派生类对象时,delete基类指针调用的是基类的析构函数,不是派生类的,如果希望调用派生类的析构函数,就要把基类的析构函数设置为虚函数;
(4)C++编辑器对虚构函数做了特别的处理;
(5)对于基类,即使它不需要析构函数,也应该提供一个虚析构函数;
(6)赋值运算符函数不能继承,派生类继承的函数的特征表与基类完全相同,但赋值运算符函数的特征表随类而异,它包含了一个类型为其所属类的形参;
(7)友元函数不是类成员,不能继承;

#include 
using namespace std;

class A
{
public:
    A(){
        cout << "基类默认构造函数A()" << endl;
    }
    virtual void func() {
        cout << "调用了基类的func()" << endl;
    }
    ~A() {
        cout << "基类析构函数~A()" << endl;
    }
};

class B : public A
{
public:
    B() {
        cout << "调用派生类默认构造函数B()" << endl;
    }
    /*void func() {
        cout << "调用了派生类的func()" << endl;
    }*/
    ~B() {
        cout << "派生类析构函数~B()" << endl;
    }
};

int main()
{
    // 1
    B* b = new B;
    b->~B();
    delete b;

    cout << "===============================================================================" << endl;

    // 2
    A* a = new B;
    delete a;
}

打印:

基类默认构造函数A()
调用派生类默认构造函数B()
派生类析构函数~B()
基类析构函数~A()
派生类析构函数~B()
基类析构函数~A()
===============================================================================
基类默认构造函数A()
调用派生类默认构造函数B()
基类析构函数~A()

// 1
调用一次b->~B()析构函数,就会调用一次基类的析构函数。
// 2
当基类的析构函数为非虚析构函数的时候,则在多态析构的时候会出问题,派生类不会调用析构函数。

当指定基类析构函数为虚函数后:

 A* a = new B;
 delete a;
基类默认构造函数A()
调用派生类默认构造函数B()
派生类析构函数~B()
基类析构函数~A()

你可能感兴趣的:(c++,c++)