C++反射和JavaScript实现

据说,C#和Java有根据类名(字符串)直接创建类对象的语法,而C++没有。C++的解决方案是什么呢?当然可以通过switch-case或if-else分支实现,看过《重构》的同学都知道,这是“坏味道”的代码。

MFC中有个“动态创建”的技术,一般是按这个思路去实现,只不过不会使用宏。思路是这样的:先登记,即将类名与创建对象的方法建立一对一的关系,通常是保存在一个map中,key是类名,value是创建对象的方法。

看一个C++的例子,参考这篇文章

//test.h
#pragma once

#include <iostream>

class Test
{
public:
	Test()
	{
		std::cout << "call Test Constructor fun" << std::endl;
	}

	~Test()
	{
		std::cout << "call Test Destructor fun" << std::endl;
	}

	void print()
	{
		std::cout << "call Test print fun" << std::endl;
	}
};

void* create_Test()
{
	Test* t = new Test;
	return (t == NULL) ? NULL : t;
}
//class_factory.h
#pragma once

#include <iostream>
#include <string>
#include <map>

typedef void* (*create_fun)();

class ClassFactory
{
private:
	ClassFactory() {};
	std::map<std::string, create_fun> my_map;
public:
	~ClassFactory() {};
	//根据类名创建对象
	void* getClassByName(std::string name)
	{
		std::map<std::string, create_fun>::iterator it = my_map.find(name);
		if (it == my_map.end())
		{
			return NULL;//没有找到类名
		}
		create_fun fun = it->second;
		if (!fun)
		{
			return NULL;
		}
		return fun();//执行函数并返回函数执行的结果
	}

	//登记类名与函数指针的对应关系
	void registClass(std::string name, create_fun fun)
	{
		my_map[name] = fun;
	}

	//单例
	static ClassFactory& getInstance()
	{
		static ClassFactory fac;
		return fac;
	}
};
//main.cpp
#include "test.h"
#include "class_factory.h"

int main()
{
	//登记
	ClassFactory::getInstance().registClass("Test", create_Test);

	//获取类对象
	Test* t = (Test*)ClassFactory::getInstance().getClassByName("Test");
	if (!t)
	{
		std::cout << "get instance Test err;" << std::endl;
		return 1;
	}

	t->print();
	delete t;
	return 0;
}

由上面的代码,再仔细看一下注册的value是什么?是create_Test,执行创建对象的函数。其实创建对象需要“构造函数”就可以了,用JavaScript改写一下上面的代码,如下:

// test.js
const { MClass_factory } = require('./class_factory');

class MTest
{
    constructor() {
        console.log("call MTest Constructor fun");
    }

    print() {
        console.log("call MTest print fun");
    }
}

MClass_factory.getInstance().registClass("MTest", MTest);
module.exports.MTest = MTest;
// class_factory.js
class MClass_factory {
    constructor() {
        this.classReg = [];
    }

    getClassByName(constructorName) {
        for (let item of this.classReg) {
            if (item['name'] === constructorName) {
                let constructorFun = item['createFun'];
                let obj = new constructorFun;
                return obj;
            }
        }
        return;
    }

    registClass(name, createFun) {
        this.classReg.push({ 'name': name, 'createFun': createFun });
    }

    static getInstance() {
        if (!this.instance) {
            this.instance = new MClass_factory();
        }
        return this.instance;
    }
}

module.exports.MClass_factory = MClass_factory;
// main.js
const { MClass_factory } = require('./class_factory');
const { MTest } = require('./test');
let objTest = MClass_factory.getInstance().getClassByName('MTest');
objTest.print();

 

发布了186 篇原创文章 · 获赞 36 · 访问量 24万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览