C++中多态的实现与参数传递方式的联系

文章讲述了C++中类的继承与多态性实现,比较了值传递、引用传递和指针传递在testFunc函数中的行为差异,强调了引用和指针传递能保持对象的原始状态,实现多态,而值传递会导致对象切片失去多态性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

class  CAnimal
{
public:
	virtual void CallFunc(){
		cout << "animal......";
	}

private:
	string m_name;
};

class  CCat : public CAnimal
{
public:
	virtual void CallFunc() override {
		cout << "miaomiaomiao......";
	}

private:
	string m_name;
};

class  CDog : public CAnimal
{
public:
	virtual void CallFunc() override {
		cout << "wangwangwang......";
	}

private:
	string m_name;
};

void testFunc(CAnimal obj) {
	obj.CallFunc();
}

int main()
{
    std::cout << "Hello World!\n";
	CCat cat;
	testFunc(cat);
}

执行结果:

 

将testFunc函数中参数传递的方式改变一下,改成引用传递。 

void testFunc(CAnimal &obj) {
	obj.CallFunc();
}

执行结果:

改成指针传递:

void testFunc(CAnimal *obj) {
	obj->CallFunc();
}

 执行结果:

会产生这种现象的原因是:

  1. 值传递(void testFunc(CAnimal obj)): 当你传递一个对象给函数时,会创建该对象的一个副本,而不是引用原始对象。在这种情况下,如果你传递一个 CCat 对象给 testFunc,会发生切片(slicing)现象,即只有 CAnimal 部分的内容会传递给函数。因此,虽然你传递了一个 CCat 对象,但函数内部处理的是一个 CAnimal 对象的副本,因此无法实现多态,因为它只知道调用 CAnimalCallFunc

  2. 引用传递(void testFunc(CAnimal &obj)): 当你传递一个对象的引用给函数时,函数操作的是原始对象,而不是对象的副本。这使得多态能够正常工作,因为它能够识别对象的实际类型,而不仅仅是基类类型。所以,在这种情况下,如果你传递一个 CCat 对象给 testFunc,它会调用 CCat 类的 CallFunc 方法,实现了多态性。

  3. 指针传递(void testFunc(CAnimal *obj)):也可以实现多态,原因在于指针引用了原始对象而不是创建对象的副本,这也符合多态的概念。引用传递(void testFunc(CAnimal &obj))和指针传递(void testFunc(CAnimal *obj))的核心思想是一致的,它们都让函数能够访问原始对象,而不是对象的副本。在 void testFunc(CAnimal *obj) 中,你传递了一个指向 CAnimal 或其派生类的指针。在运行时,这个指针可以指向任何 CAnimal 派生类的对象。因为指针是多态的,它会调用实际对象的成员函数,而不仅仅是基类的成员函数。所以,如果你传递一个 CCat 对象的指针给 testFunc,它会调用 CCat 类的 CallFunc 方法,实现了多态性。

总之,无论是引用传递还是指针传递,它们都允许函数访问原始对象,从而实现多态性。这两种方式都是在函数内部操作原始对象,而不是对象的副本,因此都能正确处理派生类的成员函数调用。而使用值传递会导致对象切片,丧失了多态性。因此,如果你想实现多态性,应该使用引用传递或指针传递,而不是值传递。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值