C++入门学习十二 多态性

多态性:基类指针在运行期间确定类型,并且必须指定基类成员函数为虚函数,然后子类对该成员函数进行重写。

重写:子类的函数名称和其他函数签名都和父类相同,要求函数参数也相同。

注意区分重载:是函数名相同,函数参数不同

override:可以在子类需要重写的成员函数添加override来限定它是重写。

final:禁止这个成员函数被它的子类重写

还有一个很重要的点:无论重写函数的访问修饰符是什么,都由基类的虚函数的访问修饰符决定

虚函数在基类声明时带有默认实参值,通过基类指针访问,总是接收基类版本的实参值。

#include <iostream>
using namespace std;


class Cat
{
public:
	Cat() = default;
	Cat(int sizeValue) :
		size{ sizeValue }
	{}


	virtual int getSize() {
		return size;
	}

	void showSize() {
		cout << getSize() << endl;
	}
protected:
	int size;
};

class SmallCat :public Cat
{
public:
	SmallCat(int sizeValue) :
		Cat{ sizeValue }
	{}
	int getSize() override final{
		return 0.5 * size;
	}
};

int main()
{
	Cat cat1{ 2 };
	Cat* p1{&cat1};
	SmallCat cat2{ 4 };
	Cat* p2{ &cat2 };
	p1->showSize();           // 2
	p2->showSize();           // 2
	return 0;
}

多态集合:

如果不存储为指针或引用,不会存储完整的派生对象。

#include <iostream>
#include <vector>
using namespace std;


class Cat
{
public:
	Cat() = default;
	Cat(int sizeValue) :
		size{ sizeValue }
	{}


	virtual int getSize() const {
		cout << "1111" << endl;
		return size;
	}

	void showSize() const{
		cout << getSize() << endl;
	}
protected:
	int size;
};

class SmallCat :public Cat
{
public:
	SmallCat(int sizeValue) :
		Cat{ sizeValue }
	{}
private:
	int getSize() const override final{
		cout << "2222" << endl;
		return 2 * size;
	}
};


int main()
{
	cout << "======1=======" << endl;
	vector<Cat> cats;
	cats.push_back(Cat(1));
	cats.push_back(SmallCat(2));
	cats.push_back(SmallCat(4));

	for (const auto& p : cats) {
		p.showSize();
	}

	cout << "======2=======" << endl;
	vector<Cat*> cats2;
	Cat cat1 = Cat(1);
	SmallCat cat2 = SmallCat(2);
	SmallCat cat3 = SmallCat(4);
	Cat* p1 = &cat1;
	Cat* p2 = &cat2;
	Cat* p3 = &cat3;
	p1->showSize();           // 2
	p2->showSize();           // 
	p3->showSize();
	cats2.push_back(p1);
	cats2.push_back(p2);
	cats2.push_back(p3);

	for (const auto& p : cats2) {
		p->showSize();
	}
}

指针和类对象之间的转换

可以把派生类对象指针隐式转换成基类指针,但是不能反过来转换。

动态强制转换使用dynamic_cast<>(),目标类型放在<>中

转换失败返回nullptr

	Cat* p1 = &cat1;
	Cat* p2 = &cat2;
	Cat* p3 = &cat3;
	SmallCat* p4 = dynamic_cast<SmallCat*>(p1);
	if (p4 == nullptr) {
		cout << "======null=======" << endl;
	}

多态会需要更多的内存

多态会创建一个特殊的指针,指向一个为类创建的函数指针表vtable

可以用typeid打印出动态类型

typeid(类对象).name()

纯虚函数

在声明函数后=0

包含至少一个纯虚函数的类叫抽象类。不能创建实例,只能创建派生类的对象。

接口:只包含纯虚函数,没有成员变量或其他函数的抽象类可以称为接口

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值