Contents

多态

多态是:

  • 同一个方法在基类和派生类中的行为不同,方法的行为取决于调用方法的对象。
  • 实现方式:
    1.在派生类中重新定义基类需要实现多态的方法
    2.使用虚方法(虚拟成员函数,在方法声明前加上virtual关键字)。编译器对虚方法采用 动态联编(将函数调用推迟到运行时决定)
  • 动态联编的原因是:继承关系中的第二条。基类指针或引用可以指向派生类对象所导致的。
class A
{
public:
void funPrint(){cout<<"funPrint of class A"<<endl;};
};

class B:public A
{
public:
void funPrint(){cout<<"funPrint of class B"<<endl;};
};

void main()
{
A *p; //定义基类的指针
A a;
B b;
p=&a;
p->funPrint();
p=&b;
p->funPrint();
}

大家以为这段代码的输出结果是什么?有的人可能会马上回答funPrint of class A 与 funPrint of class B 因为第一次输出是引用类A的实 例啊,第二次输出是引用类B的实例啊。那么我告诉你这样想就错啦,答案是funPrintof class A 与 funPrint of class A。因为p是一个A类的指针,所以不管你将p指针指向类A或是类B,最终调用的函数都是类A的funPrint 函数。这就是静态联篇,编译器在编译的时候就已经确定好了。可是如果我想实现跟据实例的不同来动态决定调用哪个函数呢?这就须要用到 虚函数(也就是动态联篇

虚函数(多态概念的c++实现)

class A
{
public:
virtual void funPrint(){cout<<"funPrint of classA"<<endl;};//虚函数
};

class B:public A
{
public:
virtual void funPrint(){cout<<"funPrint of classB"<<endl;};
};

void main()
{
A *p; //定义基类的指针
A a;
B b;
p=&a;
p->funPrint();
p=&b;
p->funPrint();
}

此时由于继承的A中调用函数是虚函数,编译器采用动态联编,结果就会出现多态性。同一个操作

(p->funprint),不同的结果。

虚基类

为了解决菱形继承体系下,类d,通过类b,类c两条途径获得类a数据的两份拷贝。和可能的命名冲突。通过让类b与类c使用虚拟继承类a来声明类a是共享的。来消除歧义

//间接基类A
class A{
protected:
    int m_a;
};

//直接基类B
class B: virtual public A{  //虚继承,则类A叫做虚基类
protected:
    int m_b;
};

//直接基类C
class C: virtual public A{  //虚继承
protected:
    int m_c;
};

//派生类D
class D: public B, public C{
public:
    void seta(int a){ m_a = a; }  //正确,如果类b,c没有声明为虚继承,则此处命名冲突
    void setb(int b){ m_b = b; }  //正确
    void setc(int c){ m_c = c; }  //正确
    void setd(int d){ m_d = d; }  //正确
private:
    int m_d;
};

int main(){
    D d;
    return 0;
}

抽象类(纯虚函数)

类中含有纯虚函数的类,纯虚函数只是一个接口,没有实现(因此,抽象类无法被实例化)。

class Vehicle
{
public:
virtual void PrintTyre()=0; //纯虚函数是这样定义的.该类为抽象类
};

class Camion:public Vehicle //继承抽象类,要实现接口,如果不实现,则该类也是抽象类
{
public:
virtual void PrintTyre(){cout<<"Camion tyrefour"<<endl;};//virtual关键字不是必需的
};

class Bike:public Vehicle
{
public:
virtual void PrintTyre(){cout<<"Bike tyre two"<<endl;};
};

void main()
{
Camion c;
Bike b;
b.PrintTyre();
c.PrintTyre();
}