c++ 对象切割示例

概念

当一个子类对象通过值传递给基类对象,如foo(Base derived_obj),这个基类的拷贝构造函数将被调用.此时子类的特性将被切割,只有基类相关操作. 也就是说如果我们向上转型如果不用引用或指针,对象将被切割.这是也我们应该传引用而不是传值的原因.

示例代码:

#include <iostream>
#include <string>

using namespace std;

class Animal{
public:
	Animal(const string& s) : name(s) {}
	virtual void eat() const {
		cout << "animal: " << name << " eat()" << endl;
	}
private:
	string name;
};

class Bird : public Animal {
private:
	string name;
	string habitat;
public:
	Bird(const string& sp, const string &s, const string &h)
		: Animal(sp), name(s), habitat(h) {};
	virtual void eat() const {
		cout << "bird: " << name << " eat() in " << habitat << endl;
	}
};

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

void WhatAreYouDoingReference(const Animal &a) {
	a.eat();
}

int main()
{
	Animal animal("Animal");
	Bird bird("Eagle","Bald","US and Canada");

	cout << "pass-by-value" << endl;
	WhatAreYouDoingValue(animal);
	WhatAreYouDoingValue(bird);

	cout << "\npass-by-reference" << endl;
	WhatAreYouDoingReference(animal);
	WhatAreYouDoingReference(bird);
}

输出结果如下:

pass-by-value

animal: Animal eat()

animal: Eagle eat()

 

pass-by-reference

animal: Animal eat()

bird: Bald eat() in US and Canada

 

分析:

注意,我们在main()函数中调用了两个函数,WhatAreYouDoingValue(Animal a)与WhatAreYouDoingReference(constAnimal &a).第一个调用是能过传值,第二个调用是传引用.

 

我们可能希望第一个调用输出 animal:Animal eat(),第二个调用输出bird: Bald eat() in US and Canada.事实上两个都是调用基类的eat.

 

为什么呢?

在传值例子中,因为eat()是被Animal 的对象执行的object.这样倒至Animal对象被进行压栈操作.这样就造成如果是值传递调用Animal默认构造函数,初始化vptr通过Animal类的vtbl并且只拷贝Animal部分.所以结果只剩下Animal部分了。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值