在c++ 20下使用微软的proxy库替代传统的virtual动态多态

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

传统的virtual动态多态经常会有下面这样的使用需求

#include <iostream>
#include <vector>

// 声明一个包含virtual虚函数的基类
struct shape
{
	virtual ~shape() {}

	virtual void draw() = 0;
};

// 派生实现virtual虚函数
struct rectangle : shape
{
	virtual void draw() override
	{
		std::cout << "rectangle" << std::endl;
	}
};

// 派生实现virtual虚函数
struct circle : shape
{
	virtual void draw() override
	{
		std::cout << "circle" << std::endl;
	}
};

int main()
{
	// 由于要用vector容器来保存各种不同的对象所以这里容器元素的类型只能使用基类指针
	std::vector<shape*> vec;

	vec.emplace_back(new rectangle());
	vec.emplace_back(new circle());

	// 通过virtual动态多态调用来实现调用真正的对象类型的成员函数
	for (const auto& p : vec)
	{
		p->draw();
	}

	// 输出
	// rectangle
	// circle
}

上面同样的需求换成proxy库来实现是这样的

#include <iostream>
#include <vector>
#include "proxy.h"

// 声明一个代理类最终会通过这个代理类去调用真正的类对象的成员函数
struct draw : pro::dispatch<void()>
{
	template <class T>
	void operator()(T& self) { self.draw(); }
};

struct shape : pro::facade<draw> {};

// 不需要派生不需要virtual虚函数
struct rectangle
{
    void draw()
    {
        std::cout << "rectangle"<< std::endl;
    }
};

// 不需要派生不需要virtual虚函数
struct circle
{
    void draw()
    {
        std::cout << "circle" << std::endl;
    }
};

int main()
{
    // 这里容器元素的类型是个proxy的代理类型
    std::vector<pro::proxy<shape>> shapes;

	shapes.emplace_back(pro::make_proxy<shape>(rectangle()));
	shapes.emplace_back(pro::make_proxy<shape>(circle()));

    // 注意这里的调用方式和virtual动态多态的调用方式不同
    for (auto& p : shapes)
    {
        p.invoke<draw>();
    }

    // 输出
    // rectangle
    // circle
}

可以看到换成proxy库之后不再有virtual虚函数而且是非侵入式的我觉得这种方式非常棒很优雅。至于性能测试我没有去做。

详情见这个开源仓库地址https://github.com/microsoft/proxy

最后编辑于2023-08-24
阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: c++