C++ 多态与虚函数

多态:多态发生在有继承的场景,基类指针调用函数时,根据对象类型不同执行不同的函数,这个特性叫多态

 

1. 在C++中,使用父类引用指向子类对象时,如果执行的函数是普通函数,则属于地址早绑定,即使传入的是子类的对象,也会执行父类的方法!

class Animal{
public:
    void speak(){
        cout<<"Animal!"<<endl;
    }
};
class Cat :public Animal{
    void speak(){//不会被执行
        cout<<"Cat!"<<endl;
    }
};
void doSpeak(Animal &animal){
    animal.speak();//地址早绑定
}
int main(){
    Cat cat;
    doSpeak(cat);//输出"Animal!"
    return 0;
}

 

2. 为了实现地址晚绑定,也就是能执行子类的方法,应把父类的方法置为虚函数,在父类方法上使用virtual关键字

class Animal{
public:
    virtual void speak(){//virtual关键字,变为虚函数
        cout<<"Animal!"<<endl;
    }
};
class Cat :public Animal{
    virtual void speak(){
        cout<<"Cat!"<<endl;
    }
};
void doSpeak(Animal &animal){
    animal.speak();//执行时动态绑定
}
int main(){
    Cat cat;
    doSpeak(cat);//输出"Cat!"
    return 0;
}

C++多态条件:有继承,子类重写父类虚函数

 

3. 虚函数表

 

 

4. 纯虚函数

通常父类实现的虚函数内容是不需要的,因此可以把虚函数改成纯虚函数

virtual void speak()=0;//不需要写实现了

当类中有了纯虚函数,它就成了抽象类,它就不能实例化对象了。

子类也必须重写父类的纯虚函数,否则不能实例化对象。

 

2023-------------

5. 如果没有使用关键字virtual,程序将根据引用类型或指针类型选择方法;如果使用了virtual,程序将根据实际对象类型选择方法

上述前提是子类重写了virtual方法,如果没重写还是继承父类的方法

 

6. 继承关系中,通常将基类的析构函数设为虚函数

如果不设为虚函数,当有父类指针指向子类对象时,父类指针delete调用的是父类析构函数,子类派生的那部分无法析构

 

7. 基类中声明了一个函数是虚函数,其派生类同名函数自动成为虚函数,派生类里可以加virtual也可以不加

 

8. 虚函数表

虚函数是通过虚函数表实现的,子类继承了几个类,就有几个虚函数表

对于使用了虚函数的类,编译器为每个对象添加了一个隐藏成员,是一个指向虚函数表地址的指针;

虚函数表存储了类对象声明的虚函数地址,如果派生类提供了虚函数的新定义,则存储位置替换为新函数地址;

程序运行时,根据虚函数表中对应第k个虚函数的地址,去实际执行类中第k个虚函数

虚函数表存放在全局数据区,虚函数表大小是编译期间确定的;虚函数表指针存放在对象实例中

posted @ 2021-02-16 12:24  Kinghao0319  阅读(28)  评论(0编辑  收藏  举报