C++对象切片和对象切片的阻止(纯虚函数让编译器强迫程序猿修改有对象切片的代码)

       下面, 我们来看一下C++中最简单的多态程序:

 

#include <iostream>
using namespace std;

class Animal
{
private:
	int weight;

public:
	virtual void eat()
	{
		cout << "eat" << endl;
	}
};


class People : public Animal
{
private:
	string language;

public:
	void eat()
	{
		cout << "chi huo" << endl;
	}
};

void fun(Animal *a)
{
	a->eat();
}

int main()
{
	People me;
	fun(&me); // chi huo

	return 0;
}

      这是指针形式的向上类型转换, 而我们又知道, 在C++中,引用是通过指针来实现的, 所以, 上面的代码也可以转换为等价的引用形式:

 

 

#include <iostream>
using namespace std;

class Animal
{
private:
	int weight;

public:
	virtual void eat()
	{
		cout << "eat" << endl;
	}
};


class People : public Animal
{
private:
	string language;

public:
	void eat()
	{
		cout << "chi huo" << endl;
	}
};

void fun(Animal &a)
{
	a.eat();
}

int main()
{
	People me;
	fun(me);  // chi huo

	return 0;
}


       

 

       好, 我们来看看非指针、引用形式的向上类型转换:

 

#include <iostream>
using namespace std;

class Animal
{
private:
	int weight;

public:
	virtual void eat()
	{
		cout << "eat" << endl;
	}
};


class People : public Animal
{
private:
	string language;

public:
	void eat()
	{
		cout << "chi huo" << endl;
	}
};

void fun(Animal a)
{
	a.eat();
}

int main()
{
	People me;
	fun(me);  // eat

	return 0;
}

       可以看到, 程序的结果是eat, 而不是chi huo,  这又是为什么呢? 原来, 是对象被切片了, 被切割了。  当发生a=me;赋值操作的时候, 由于a和me的容量并不相同(a小me大), 所以a仅仅能容纳me的一部分, 对于编译器来说, 当发生a=me;后, 在fun内部, me的信息丢失了, 即me被切割了, 编译器的眼中全是Animal类型的a。 所以编译器丝毫感觉不到me的存在, a就是a了, 因此, 上面程序的结果自然就是eat.

 

       上面的现象就是对象的切片, 实际上, 对象的切片容易让程序产生错误, 也无法实现预定的多态功能。 所以, 要避免对象切片, 那该怎么办呢? 不让Animal创建对象不就行了么, 对, 就是这样, 用纯虚函数来做。 让代码产生编译器错误, 强迫程序猿改正错误, 如下:

 

#include <iostream>
using namespace std;

class Animal
{
private:
	int weight;

public:
	virtual void eat() = 0;
};


class People : public Animal
{
private:
	string language;

public:
	void eat()
	{
		cout << "chi huo" << endl;
	}
};

void fun(Animal a) // error
{
	a.eat();
}

int main()
{
	People me;
	fun(me);

	return 0;
}

       这样, 就有了编译错误, 从而强迫程序猿修改, 避免非指针、引用形式的向上类型转换 (对象切片)。 
 

 

 


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值