C++ 包装器与绑定器的应用之如何取代虚函数

C++虚函数在执行过程中会跳转两次(先查找对象的函数表,再次通过该函数表中的地址找到真正的执行地址),这样的话,CPU会跳转两次,而普通函数只跳转一次。

CPU每跳转一次,预取指令要作废很多,所以效率会很低.

为了管理的方便(基类指针可指向派生类对象和自动析构派生类),保留类之间的继承关系。

使用基类指针指向派生类对象时,基类的析构函数应是虚函数,否则释放基类指针所指的对象时只会调用基类的析构函数. 

代码示例:

#include          // 包含头文件。

#include 

using namespace std;


struct Hero { // 英雄基类

	//virtual void show() { cout << "英雄释放了技能。\n"; }

	function m_callback;        // 用于绑定子类的成员函数。



	// 注册子类成员函数,子类成员函数没有参数。

	template

	void callback(Fn&& fn, Args&&...args) {

		m_callback = bind(forward(fn), forward(args)...); //注意格式

	}

	void show() { m_callback(); }   // 调用子类的成员函数。

	virtual ~Hero() {
		cout << "调用了基类的析构函数" << endl;
	}

};



struct LY :public Hero { // LY派生类
	function m_callback;

	void show() { cout << "流萤释放了战技。\n";
	if(LY::m_callback)
			LY::m_callback();
	}
	~LY() {
		cout << "调用了流萤类的析构函数" << endl;
	}
};



struct LS :public Hero { // LS派生类

	function m_callback;

	void show() {
		cout << "灵砂释放了终结技。\n";
		if(LS::m_callback)
			LS::m_callback();
	}
	~LS() {
		cout << "调用了灵砂类的析构函数" << endl;
	}
};



int main()

{

	// 根据用户选择的英雄,施展技能。

	int id = 0;     // 英雄的id。

	cout << "请输入角色(1-流萤;2-灵砂。):";

	cin >> id;



	// 创建基类指针,将指向派生类对象,用基类指针调用派生类的成员函数。

	Hero* ptr = nullptr;



	if (id == 1) {            // 1-西施

		ptr = new LY;

		ptr->callback(&LY::show, dynamic_cast(ptr));  // 注册子类成员函数,调用父类的callback函数,初始化父类m_callback函数对象.
		
	}

	else if (id == 2) {     // 2-韩信

		ptr = new LS;

		ptr->callback(&LS::show, dynamic_cast(ptr));  // 注册子类成员函数,调用父类的callback函数,初始化父类m_callback函数对象.

	}



	if (ptr != nullptr) {

		ptr->show(); // 调用子类的成员函数。

		delete ptr; // 释放派生类对象。

	}

}

注:此课件及源代码来自B站up主:码农论坛,该文章仅作为本人学习笔记及交流学习使用。   

你可能感兴趣的:(C++,学习之路,c++,开发语言,学习,笔记)