more effective c++读书笔记 第五章 技术 part2

本文探讨了在C++中如何根据对象类型实现多态行为。介绍了三种方法:RTTI的if-else结构、函数重载和自定义虚函数表。每种方法都有其优缺点,RTTI可能导致性能损失,函数重载违反开闭原则,而自定义虚函数表虽然减少if-else,但仍然需要维护。文章鼓励寻找更好的解决方案以遵循开闭原则。
摘要由CSDN通过智能技术生成

条款31

让函数根据一个以上的对象类型决定如何虚化

这里的问题很简单


class Base {
virtual void funtion( Base& base){}
};
class A : public base {};
class B : public base {};
class C : public base {};

现在,function 的参数都可能是A B C中的一个,但是不同的参数类型有不同的行为,如何根据参数类型决定funcion中的行为呢。因为是虚函数,所以在函数调用时,如 A.funtion(…),已经完成了一次消息派发,但是在不同派生类中的虚函数,还需要知道虚函数的参数类型,显然首先会想到RTTI,也就是说,可能会这么写:

class A : public base {
virtual void funtion(Base& base) {
	if (typeid(base) == typeid(A)) {
	
	} else if (typeid(base) == typeid(B)) {

	} .....
}
};

这样做,的确可以完成,但是缺点很多,比如,添加或删除一个派生时,需要到所有派生类中修改,违反了开闭原则,而且,typeid对性能有影响。

第二种方法:
只使用虚函数:

class A : public Base {
virtual void funtion(A& ) {};
virtual void function(B& ) {};
...
};

使用函数重载,也完成了第二次类型派发(第一次是虚函数被调用),这里就好多了,没有RTTI, 没有if else,但是还有问题,还是违反了开闭原则。

第三种方法:
使用仿真的虚函数表格:
第一次类型派发由调用虚函数的对象来派发,问题是第二次,前面我们用了RTTI来逐个区分,用重载让编译来派发,这里是我们模仿虚函数的行为,自己来派发类型

class A : public Base {
public:
	virtual void function(Base&) {}
	virtual void AandB(B&) {}
	virtual void AandC(C&) {}
	using fptr =  void (A::*(Base&);
 	fptr findFunc(Base& type) {
 		static map<string, fptr> funcMap = init();
 		auto it = funcMap.find(typeid(type).name());
 		if (it != funcMap.end()) {
			return it->second;
		}
		return nullptr;
 	}
 	static init() {
		funcMap[typeid(A).name()] = ...
		funcMap[typeid(B).name()] = ...
	}
	.....
};

这样,我们手动构造了一个函数指针的map,这样就在函数内部,通过map找到了需要的函数。
这里依然使用了RTTI, 不过对于这个,好像作者也没有给出好办法。这里也违反了开闭原则,不过作者给出了一种方法,将function函数内部的处理放到非成员函数中,在function 函数中只用findFunc函数用来查找非成员函数然后调用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值