多态与虚继承

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/cmh477660693/article/details/69474400

多态性是指具有不同功能的函数可以用同一个函数名,这样就可以用一个函数调用不同内容的函数。多态主要通过联编实现。
静态联编:在编译时一定确定要调用哪个函数。
动态联编:一个类如果有虚函数,它的对象有个指针,指向虚函数表,通过指针调用里面的虚函数。
虚函数表8个字节。
在类的继承的不同层次中,在不同的层次中可以出现名字、参数个数和类型相同而功能不同的函数。编译器按照向自己后父类的顺序进行覆盖查找,如果子类有与父类相同原形的成员函数,要想调用父类的成员函数,需要对父类重新引用调用。虚函数则可以解决子类和父类相同原型成员函数的函数调用问题。虚函数允许在派生类中重新定义域基类同名的函数,并且可以通过基类指针或引用来访问基类和派生类的同名函数。
在基类中用virtual声明成员函数为虚函数,在派生类中重新定义此函数,改变此函数的功能。在C++语言中虚函数可以继承,当一个成员函数被声明为虚函数后,其派生类中的同名函数都自动成为虚函数。但如果派生类没有覆盖基类的虚函数,则调用时调用基类的函数定义。
覆盖和重载的区别是:重载是同一层次函数名相同,覆盖是在继承层次中成员函数的函数原型完全相同。
根据联编的时刻不同,存在两种类型的多态性。及函数重载和虚函数。

利用虚函数实现多态

多态主要体现在虚函数上,只要虚函数存在,对象类型就会在程序运行时动态绑定。动态绑定的实现方法就是定义一个指向基类对象的指针变量,并使它指向同一类族中函数中需要调用该函数的对象,通过该指针变量调用此虚函数。

基类和子类的对象如何实现调用各自类的函数。通过虚函数实现。
传值得时候

是否可以为虚函数的情况

1.只有类的成员函数才能声明为虚函数。
2.静态成员函数不能是虚函数。
3.内联函数不能是虚函数。
4.构造函数不能是虚函数
5.析构函数一般声明为虚函数。为了调用各自的析构函数。销毁子类的对象会先调用基类的析构函数,在调用子类的析构函数。
6.重载:函数参数不同,不可设为虚函数。
7.覆盖:函数参数,返回值相同,可以设为虚函数。
8.返回值例外:
函数参数相同:但是返回值是当前对象的指针或引用时,也可以设置为虚函数。

这里写图片描述

#include<iostream>
#include<string.h>
#include<unistd.h>
using namespace std;
class Human{
    public:
    virtual void eating(void){
        cout<<"use hand to eat"<<endl;
    }
    //void test_eating(Huamn &h);
};
class Englishman:public Human{
    public:
    void eating(void)
    {
        cout<<"use knife to eat"<<endl;
    }
};
class Chinese:public Human{
    public:
    void eating(void)
    {
        cout<<"use chopstickes to eat"<<endl;
    }
};
void test_eating(Human &h)
{
    h.eating();
}
int main()
{
    Human h;
    Englishman e;
    Chinese c;
    test_eating(h);
    test_eating(e);
    test_eating(c);
    return 0; 
}

虚拟继承

#include<iostream>
#include<string.h>
#include<unistd.h>
using namespace std;
class Furniture{
private:
    int weight;
public: 
    void setWeight(int weight){
        this->weight=weight;
    }
    int getWeight(void)const
    {
        return weight;
    }
};
class Sofa:virtual public Furniture
{   

public:
    void watchTV(void){
        cout<<"watch TV"<<endl;
    }   
};
class Bed:virtual public Furniture{
    public:
        void sleep(void){
            cout<<"sleep"<<endl;
        }
};
class Sofabed:public Sofa,public Bed{

};
int main(int argc,char *argv[])
{
    Sofabed s;
    s.sleep();
    s.watchTV();
    s.setWeight(100);
}

构造函数的顺序:
先父后儿
1.先调用基类的构造函数
1.1先虚拟基类
1.2先一般基类
2.自身
2.1先对象成员
2.2后自己
(虚拟基类构造函数只执行一次)

#include<iostream>
#include<string.h>
#include<unistd.h>
using namespace std;
class Furniture{
private:
    int weight;
public: 
    void setWeight(int weight){
        this->weight=weight;
    }
    int getWeight(void)const
    {
        return weight;
    }
    Furniture(){
        cout<<"Furniture()"<<endl;
    }
};
class Vertification3C{
    public:
    Vertification3C(){
        cout<<"Vertification3C()"<<endl;
    }

};
class Sofa:virtual public Furniture,virtual public Vertification3C
{   
    private:
        int a;
    public:
        void watchTV(void){
            cout<<"watchTV"<<endl;
        }
        Sofa(){
            cout<<"Sofa()"<<endl;
        }
};
class Bed:virtual public Furniture,virtual public Vertification3C{
    private:
        int b;
    public:
        void sleep(void){
            cout<<"sleep"<<endl;
        }
        Bed(){
            cout<<"Bed()"<<endl;
        }
};

class Sofabed:public Sofa,public Bed{
    private:
        int c;
    public:
    Sofabed(){
        cout<<"Sofabed()"<<endl;
    }

};
class LeftRightCom{
        public:
        LeftRightCom(){
            cout<<"LeftRightCOm()"<<endl;
        }

};
class Date{
    public:
        Date(){
            cout<<"Date()"<<endl;
        }
};
class Type{
    public:
        Type(){
            cout<<"Type()"<<endl; 
        }
};
class LeftRightSofabed:public Sofabed,public LeftRightCom{
    private:
        Date date;
        Type type;
    public:
        LeftRightSofabed(){
            cout<<"LeftRightSofabed"<<endl;
        }

};
int main(int argc,char *argv[])
{
    LeftRightSofabed s;
    return 0;

}

这里写图片描述

猜你喜欢

转载自blog.csdn.net/cmh477660693/article/details/69474400