详解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对象的位置。

虚基表和虚表通常存在常量区。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值