一、c++如何解决菱形继承的问题
例子一
菱形继承问题
#include <iostream>
#include <string.h>
using namespace std;
class Animal
{
public:
int m_Age;
};
class Sheep : public Animal {};
class Tuo : public Animal {};
class SheepTuo :public Sheep, public Tuo
{
public:
};
void test()
{
SheepTuo st;
st.Sheep::m_Age = 100;
st.Tuo::m_Age = 200;
cout << "st.Sheep::m_Age = " << st.Sheep::m_Age << endl;
cout << "st.Tuo::m_Age = " << st.Tuo::m_Age << endl;
cout << "st.m_Age = " << st.m_Age << endl;//err
}
void main()
{
test();
}
例子二
解决菱形继承的问题
#include <iostream>
#include <string.h>
using namespace std;
class Animal
{
public:
int m_Age;
};
class Sheep :virtual public Animal {};
class Tuo :virtual public Animal {};
class SheepTuo :public Sheep, public Tuo
{
public:
};
void test()
{
SheepTuo st;
st.Sheep::m_Age = 100;
st.Tuo::m_Age = 200;
cout << "st.Sheep::m_Age = " << st.Sheep::m_Age << endl;
cout << "st.Tuo::m_Age = " << st.Tuo::m_Age << endl;
cout << "st.m_Age = " << st.m_Age << endl;//err
}
void main()
{
test();
}
二、c++中的多态
多态的分类
1、静态多态:函数重载与运算符重载(本质可以裂解为函数重载)都属于静态多态,复用函数名
2、动态多态:派生类和虚函数实现运行时多态
静态多态与动态多态的区别:
1、静态多态的函数地址早绑定 - 编译阶段确定函数地址
2、动态多态的函数地址晚绑定 - 运行阶段确定函数地址(利用virtual关键字)
例子一
继承,编译阶段即确定调用的函数
#include <iostream>
#include <string.h>
using namespace std;
//多态的分类
//1、静态多态:函数重载与运算符重载(本质可以裂解为函数重载)都属于静态多态,复用函数名
//2、动态多态:派生类和虚函数实现运行时多态
//
// 静态多态与动态多态的区别:
//1、静态多态的函数地址早绑定 - 编译阶段确定函数地址
//2、动态多态的函数地址晚绑定 - 运行阶段确定函数地址(利用virtual关键字)
//
class Animal
{
//这里是地址早绑定,静态绑定
public:
void speak()
{
cout << "Animal speak" << endl;
}
};
class Cat :public Animal
{
public:
void speak()
{
cout << "Cat speak" << endl;
}
};
class Dog :public Animal
{
public:
void speak()
{
cout << "Dog speak" << endl;
}
};
//无论传入的是cat对象还是dog对象,执行的都是Animal的speak方法,这里是地址早绑定,静态绑定
//编译阶段就确定了调用方法
void doSpeak(Animal& animal)
{
animal.speak();
}
void test()
{
Cat cat;
Dog dog;
doSpeak(dog);
}
void main()
{
test();
}
例子二
利用virtual,虚函数的概念,动态绑定调用的函数
#include <iostream>
#include <string.h>
using namespace std;
//多态的分类
//1、静态多态:函数重载与运算符重载(本质可以裂解为函数重载)都属于静态多态,复用函数名
//2、动态多态:派生类和虚函数实现运行时多态
//
// 静态多态与动态多态的区别:
//1、静态多态的函数地址早绑定 - 编译阶段确定函数地址
//2、动态多态的函数地址晚绑定 - 运行阶段确定函数地址(利用virtual关键字)
//
class Animal
{
//这里是地址早绑定,静态绑定
public:
virtual void speak()
{
cout << "Animal speak" << endl;
}
};
class Cat :public Animal
{
public:
//这里子类(派生类)的virtual可以省略 override表示复写积累中的方法
virtual void speak() override
{
cout << "Cat speak" << endl;
}
};
class Dog :public Animal
{
public:
void speak()
{
cout << "Dog speak" << endl;
}
};
//根据传入的对象cat对象还是dog对象,来决定执行的都是Cat的speak方法,还是Dog的speak方法
//这里是函数地址晚绑定,动态绑定
//运行阶段确定调用方法
void doSpeak(Animal& animal)
{
animal.speak();
}
void test()
{
Cat cat;
Dog dog;
doSpeak(dog);
}
void main()
{
test();
}
c++多态的原理
下图中的vfprt都是同一个指针,子类会继承父类的虚函数指针与虚函数表,如果发生了子类覆写了父类的virtual的方法,则会子类中的虚函数表的方法会替换成子类的方法指针