详解c++菱形继承和多态---下
菱形继承
#include<iostream>using namespace std;
class Animal
{
public:int m_Age;
};
class Sheep : public Animal {};
class Tuo : public Animal {};
class SheepTuo : public Sheep, public Tuo {};
void test()
{SheepTuo st;st.Sheep::m_Age = 18;st.Tuo::m_Age = 20;cout << "st.Sheep::m_Age: " << st.Sheep::m_Age << endl;cout << "st.Tuo::m_Age: " << st.Tuo::m_Age << endl;}
int main()
{test();return 0;
}
菱形继承数据存在二义性问题。
cl /d1 reportSingleClassLayoutSheepTuo test.cpp
虚继承
class Sheep : virtual public Animal {};
class Tuo : virtual public Animal {};
class SheepTuo : public Sheep, public Tuo {};
多态
动态多态
满足条件
1.有继承关系
2.子类重写父类的虚函数
使用
父类的指针或引用执行子类对象。
重写
函数返回值类型,函数名,参数列表完全一致。
class Animal
{
public:virtual void speak(){cout << "Animal speak()" << endl;}
};
class Cat : public Animal
{
public:void speak(){cout << "Cat speak()" << endl;}
};
void doSpeak(Animal& animal)
{animal.speak();
}
void test()
{Cat cat;doSpeak(cat);
}
Animal类的大小为4,不加virtual大小为1(空类的大小为1)。
子类重写父类的虚函数,子类的虚函数表内部会替换为子类的虚函数地址。
class AbstractCalculator
{
public:virtual int getResult(){return 0;}int m_Num1;int m_Num2;
};
class AddCalculator :public AbstractCalculator
{
public:int getResult(){return m_Num1 + m_Num2;}
};
class SubCalculator :public AbstractCalculator
{
public:int getResult(){return m_Num1 - m_Num2;}
};
void test()
{AbstractCalculator* ac = new AddCalculator;ac->m_Num1 = 1;ac->m_Num2 = 2;cout << ac->getResult() << endl;
}
纯虚函数和抽象类
class AbstractDrinking
{
public:virtual void Boil() = 0;virtual void Brew() = 0;virtual void PourInCup() = 0;virtual void PutSomething() = 0;void makeDrink(){Boil();Brew();PourInCup();PutSomething();}
};
class Coffee :public AbstractDrinking
{virtual void Boil() { cout << "Boil Coffee" << endl; };virtual void Brew() { cout << "Brew Coffee" << endl; };virtual void PourInCup() { cout << "PourInCup Coffee" << endl; };virtual void PutSomething() { cout << "PutSomething Coffee" << endl; };
};
void doWork(AbstractDrinking* ad)
{ad->makeDrink();
}
虚析构和纯虚析构
父类指针在析构的时候,不会调用子类中的析构函数,导致如果子类有堆区属性会出现内存泄漏。
class Animal
{
public:Animal(){cout << "Animal()" << endl;}virtual ~Animal(){cout << "~Animal()" << endl;}virtual void speak() = 0;
};
class Cat : public Animal
{
public:Cat(string name){cout << "Cat()" << endl;m_Name = new string(name);}void speak(){cout <<*m_Name<< "Cat speak()" << endl;}~Cat(){if (m_Name != nullptr){cout << "~Cat()" << endl;delete m_Name;m_Name = nullptr;}}string* m_Name;
};
void test()
{Animal* animal = new Cat("Tom");animal->speak();delete animal;
}
通过虚析构解决。
纯虚析构
virtual ~Animal() = 0;
Animal::~Animal()
{cout << "virtual ~Animal()" << endl;
}
需要有声明及实现。
总结
虚基表中存偏移量,用于计算X中虚基类XX对象的位置。
虚基表和虚表通常存在常量区。