C++笔记 33:将非尾端设计成抽象类

More Effective C++笔记

将非尾端设计成抽象类

多态型对象赋值

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

class Animal
{
public:
	Animal &operator=(const Animal& rhs) { return *this; };
};

class Lizard : public Animal
{
public:
	Lizard &operator=(const Lizard& rhs) { return *this; };
};

class Chicken : public Animal
{
public:
	Chicken &operator=(const Chicken& rhs) { return *this; };
};

void test01()
{
	Lizard liz1;
	Lizard liz2;
	Animal *pAni1 = &liz1;
	Animal *pAni2 = &liz2;
	*pAni1 = *pAni2;	//调用Animal::operator=, Animal *指针具有多态性,只进行部分赋值
}

声明成虚函数

在这里插入图片描述
在这里插入图片描述

class Animal
{
public:
	virtual Animal &operator=(const Animal& rhs) { return *this; };
};

class Lizard : public Animal
{
public:
	virtual Lizard &operator=(const Animal& rhs) { return *this; };
};

class Chicken : public Animal
{
public:
	virtual Chicken &operator=(const Animal& rhs) { return *this; };
};

void test02()
{
#if 0
	Lizard liz1;
	Lizard liz2;
	Animal *pAni1 = &liz1;
	Animal *pAni2 = &liz2;
	*pAni1 = *pAni2;	//调用Lizard::operator=  
#endif // 0

	Lizard liz;
	Chicken chick;
	Animal *pAni1 = &liz;
	Animal *pAni2 = &chick;
	*pAni1 = *pAni2;	//调用Lizard::operator=  chick赋值給liz不合理
}

dynamic_cast解决混合类型赋值

在这里插入图片描述

class Animal
{
public:
	virtual Animal &operator=(const Animal& rhs) { return *this; };
};

class Lizard : public Animal
{
public:
	virtual Lizard &operator=(const Animal& rhs) 
	{ 
		//make sure rhs is really a lizard
		const Lizard& rhs_liz = dynamic_cast<const Lizard&>(rhs);
		//給类成员赋值...
		return *this; 
	};
};

class Chicken : public Animal
{
public:
	virtual Chicken &operator=(const Animal& rhs) { return *this; };
};

void test03()
{
	Lizard liz;
	Chicken chick;
	Animal *pAni1 = &liz;
	Animal *pAni2 = &chick;
	*pAni1 = *pAni2;	//调用Lizard::operator=  抛出bad_cast异常
}

增加一个通常形式的赋值操作

在这里插入图片描述
在这里插入图片描述

class Animal
{
public:
	virtual Animal &operator=(const Animal& rhs) { return *this; };
};

class Lizard : public Animal
{
public:
	virtual Lizard &operator=(const Animal& rhs) 
	{ return operator=(dynamic_cast<const Lizard&>(rhs)); };
	Lizard &operator=(const Lizard& rhs) { return *this; };
};

class Chicken : public Animal
{
public:
	virtual Chicken &operator=(const Animal& rhs) { return *this; };
};

void test04()
{
	Lizard liz;
	Lizard liz2;
	liz = liz2;			//调用Lizard::operator=(const Lizard& rhs)

	Chicken chick;
	Animal *pAni1 = &liz;
	//Animal *pAni2 = &liz2;	//可以
	Animal *pAni2 = &chick;		//抛出bad_cast异常
	*pAni1 = *pAni2;	//调用Lizard::operator=(const Animal& rhs)
}

将Animal operator=置为private,使在编译器报错

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

class Animal
{
protected:
	virtual Animal &operator=(const Animal& rhs) { return *this; };
};

class Lizard : public Animal
{
public:
	Lizard &operator=(const Lizard& rhs) { return *this; };
};

class Chicken : public Animal
{
public:
	Chicken &operator=(const Animal& rhs) { return *this; };
};

void test04()
{
	Lizard liz;
	Chicken chick;
	Animal *pAni1 = &liz;
	Animal *pAni2 = &chick;	
	//*pAni1 = *pAni2;		//chick赋值給liz调用Animal::operator=报错
	//1.Anima对象之间赋值也报错
	//2.派生类赋值有责任调用基类赋值函数,将Animal::operator=申明为 protected 来解决
}

使用抽象类

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

class AbstractAnimal
{
protected:
	AbstractAnimal &operator=(const AbstractAnimal& rhs) { return *this; };
public:
	virtual ~AbstractAnimal() {};
};

class Animal : public AbstractAnimal
{
protected:
	Animal &operator=(const Animal& rhs) { return *this; };
};

class Lizard : public AbstractAnimal
{
public:
	Lizard &operator=(const Lizard& rhs) { return *this; };
};

class Chicken : public AbstractAnimal
{
public:
	Chicken &operator=(const Animal& rhs) { return *this; };
};

void test04()
{
	Lizard liz;
	Chicken chick;
	AbstractAnimal *pAni1 = &liz;
	AbstractAnimal *pAni2 = &chick;
	//*pAni1 = *pAni2;		//chick赋值給liz调用AbstractAnimal::operator= 没有权限访问(protected)
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值