反射とプラグインのプログラミングC ++

リフレクションは、実質的にクラス文字列のクラス名、メソッド名の文字列を呼び出すする方法のインスタンスによって生成されます。C ++では、一見してこのブログを参照することができ、反射メカニズムをサポートしていない数多くの夜|のC ++反射を実現する反射C ++実装にはいくつかの「ラウンドアバウト」の方法で。

  • リフレクションの使用は何ですか?-生成されたクラスまたは関数を決定することができる反射は、実行時に呼び出されます。
    そのようなプラグインプログラムにする必要性として、主プログラム全体メインプログラムを再コンパイルすることなく、プラグインのメインプログラムへとして添加することができる様々な新機能を追加するためのインタフェースを提供します。これを行うには、あなたはプラグインのdllファイル、実行時に、メインプログラムの下に置かれたと呼ばれることができます。これらのプラグインは、統一されたインターフェイスから継承する必要がありますが、このインタフェースは、メインプログラムで定義され、メインプログラムは、あなたは、これらの「新機能を知ることができるように「一貫して使用。唯一の問題は、今のプラグインは、メインプログラムで定義されたクラスを生成するために必要である、あなたはそのコンストラクタを使用する必要がありますが、これらのプラグインは、将来の可能性があるため、これらのプラグインのクラスの彼らの主なコンストラクタの名前を知りませんでしたユーザー自身の発展、コンパイル時にメインプログラムを知ることは不可能です。メインプログラムでは、彼らだけが標準化されたファイルの命名に従うならば言葉(例えばプラグの名前などがあり、作業ディレクトリ内のファイルプラグインはどのような現在のランタイムDLLを学ぶことができる类名_plugin.dll)ので、プラグインのメインクラスの名前を推測することができますが、その後、問題がダウンしていますこれは、生成されたクラスの名前の文字列になりました。
  • 主なアイデアは、次のとおりです。
  1. ファクトリ(工場)クラスの定義は、このクラス情報管理クラスを反映し、そのようなグローバルな反射情報の具体例を作成するための関数は、次のクラス名で、クラス・オブジェクト・マップである、マッピングテーブルを維持将来クラス情報検索文字列(情報は、クラス名、およびその他の情報ポインタコンストラクタ含んでいてもよい);コンストラクタのインデックスに従って指定されたクラスファクトリクラス名文字列のインスタンスを作成し、そのコンストラクタを使用してそれ自体を構成しました
  2. あなたはそれがクラスに反射機能を実現したい場合は、カスタム後のクラスでは、維持すべきであるClassInfo自分自身を登録する同等の(自分の情報の保持クラスに静的メンバ変数を、情報のマッピングテーブルを反映した情報を登録するには、ユーザーの後に)自分のコンストラクタを見つけることができます
  • 次のように私は少し、私は夜のブログの例複雑少し読んものを変更します:
//reflex.h
#ifndef REFLEX_H
#define REFLEX_H
#include <string>
#include <map>

#define CONSTRUCTOR(class_name)\
public:\
static ReflexBase* CreateObject()\
{\
	return new class_name;\
}\
protected:\
static ClassInfo m_classInfo;

#define REGISTER_REFLEX(class_name)\
ClassInfo class_name::m_classInfo(#class_name,class_name::CreateObject);

class ClassInfo;
class ReflexBase;
static std::map<std::string, ClassInfo*> *m_classInfoMap;

class Factory 
{
public:
	Factory() {}
	virtual ~Factory() {}
	static bool Register(ClassInfo *pCInfo);
	static ReflexBase* CreateObject(std::string className);
	static ClassInfo* GetClassInfo(std::string className);
};
typedef ReflexBase* (*objConstructorFun)();
class ClassInfo
{
public:
	ClassInfo(const std::string className, objConstructorFun classConstructor) :
		m_className(className), m_objConstructor(classConstructor)
	{
		Factory::Register(this);
	}
	virtual ~ClassInfo() {}
	ReflexBase* CreateObject()const { return m_objConstructor ? (*m_objConstructor)() : NULL; }
	bool IsDynamic()const { return NULL != m_objConstructor; }
	const std::string GetClassName()const { return this->m_className; }
	objConstructorFun GetConstructor()const { return this->m_objConstructor; }
private:
	std::string m_className;
	objConstructorFun m_objConstructor;
};

class ReflexBase
{
public:
	ReflexBase() {}
	virtual ~ReflexBase() {}
};
#endif

そのソースファイル:

//reflex.cpp
#include "stdafx.h"
#include "reflex.h"
#include <map>


bool Factory::Register(ClassInfo * pCInfo)
{
	if (!m_classInfoMap) {
		m_classInfoMap = new std::map<std::string, ClassInfo*>();
	}
	if (!pCInfo) {
		return false;
	}
	if (m_classInfoMap->end() == m_classInfoMap->find(pCInfo->GetClassName())) {
		m_classInfoMap->insert(std::map<std::string, ClassInfo*>::value_type(pCInfo->GetClassName(), pCInfo));
	}
	return true;
}

ReflexBase * Factory::CreateObject(std::string className)
{
	std::map<std::string, ClassInfo*>::const_iterator c_iter = m_classInfoMap->find(className);
	if (m_classInfoMap->end() != c_iter) {
		return c_iter->second->CreateObject();
	}
	return NULL;
}

ClassInfo * Factory::GetClassInfo(std::string className)
{
	std::map<std::string, ClassInfo*>::const_iterator c_iter = m_classInfoMap->find(className);
	if (m_classInfoMap->end() != c_iter) {
		return c_iter->second;
	}
	return NULL;
}

定義した上でFactory使用して、管理するためのクラスの反射機構ReflexBase基底クラスのみ反射を、機能はありません。あなたが作る必要がある場合は、より(簡体字)よりも反射を使用して独自のクラスを使用しているとき、あなたはあなたのクラスの継承を行うことができますReflexBaseクラス(またはそのサブクラス)。例えば、プラグイン開発は、あなたが使用している場合、上記のReflexBase:私たちは、特定のプラグいくつかのインタフェースに沿ったもので、将来的に必要がある場合がありますので、基本クラスのプラグインが、あまりにもシンプルなようなので、2つのアイデアがあります

  • カスタムプラグインとプラグインインタフェースから継承したReflexBaseクラス。しかし、ここで使用される複数の継承は推奨されません。
  • プラグインからインターフェイスクラス継承ReflexBase、カスタムプラグインのプラグインインタフェースから継承したクラス、。実現可能な測定。
    次のようにサンプルコードは次のとおりです。
//test_reflex.cpp
// TestReflec.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <string>
#include "reflex.h"
class Plugin:public ReflexBase
{
public:
	Plugin();
	virtual ~Plugin();
	virtual void func();//将来插件要实现的功能
};
class PluginA :public Plugin
{
public:
	PluginA();
	~PluginA();
	//使用CONSTRUCTOR宏给该插件构造工厂函数
	CONSTRUCTOR(PluginA)
	void func();
};
//注册该插件类的信息
REGISTER_REFLEX(PluginA)

class PluginB :public Plugin
{
public:
	PluginB();
	~PluginB();
	CONSTRUCTOR(PluginB)
	void func();
};
REGISTER_REFLEX(PluginB)

int main()
{
	Plugin* test = (Plugin*)(Factory::CreateObject("PluginA"));
	std::cout << "test class name=" << Factory::GetClassInfo("PluginA")->GetClassName() << ",constructor add[" << Factory::GetClassInfo("PluginA")->GetConstructor() << std::endl;
	test->func();
	Plugin* test1 = (Plugin*)(Factory::CreateObject("PluginB"));
	std::cout << "test1 class name=" << Factory::GetClassInfo("PluginB")->GetClassName() << ",constructor add[" << Factory::GetClassInfo("PluginB")->GetConstructor() << std::endl;
	test1->func();
	delete test;
	delete test1;
	system("pause");
	return 0;
}

PluginA::PluginA()
{
	std::cout << "ADDR:[" << std::hex << (long)this << "].The Object Name is \"PluginA\" constructed!" << std::endl;
}

PluginA::~PluginA()
{
	std::cout << "ADDR:[" << std::hex << (long)this << "].The Object Name is \"PluginA\" destroyed!" << std::endl;
}

void PluginA::func()
{
	std::cout << "func in PluginA class exec..." << std::endl;
}

PluginB::PluginB()
{
	std::cout << "ADDR:[" << std::hex << (long)this << "].The Object Name is \"PluginB\" constructed!" << std::endl;
}

PluginB::~PluginB()
{
	std::cout << "ADDR:[" << std::hex << (long)this << "].The Object Name is \"PluginB\" destroyed!" << std::endl;
}

void PluginB::func()
{
	std::cout << "func in PluginB class exec..." << std::endl;
}

Plugin::Plugin()
{
	std::cout << "ADDR:[" << std::hex << (long)this << "].The Object Name is \"Plugin\" constructed!" << std::endl;
}

Plugin::~Plugin()
{
	std::cout << "ADDR:[" << std::hex << (long)this << "].The Object Name is \"Plugin\" destroyed!" << std::endl;
}

void Plugin::func()
{
	std::cout << "func in Plugin class exec..." << std::endl;
}

結果:
ここに画像を挿入説明
ここにあなたが多重継承の方法を使用している場合、ある、場合:

class Plugin//这里不继承ReflexBase
{
	...
}
class PluginA:pubic Plugin,public ReflexBase
{
	...
}

それはそう主な機能で構築されるため、その後、アクセス違反が発生しますPluginオブジェクトの。

Plugin* test = (Plugin*)(Factory::CreateObject("PluginA"));

実際にここで使用Factory::Create構築ReflexBase*のタイプを、あなたはサブクラスのポインタに有効にする必要がありますに変換しPlugin*ているため、ReflexBasePluginノー継承、どの2つが直接ターンの種類に関係していないされていない、次のように、それは次のようになります。

Plugin* test = (Plugin*)(PluginA*)(Factory::CreateObject("PluginA"));

しかし、これは完全に直接反射を必要としないことを、プラグインJiaoshaの将来の発展を知るために、メインプログラムのコンパイル時に相当します。

Plugin *test=new PluginA();

これは、この場合には、複数の継承方法の実際のニーズを満たしていない不適切です。
別の考慮事項がすることですPluginから継承しReflexBasePluginAから継承Pluginし、ReflexBaseこの愚かな、これをしません。

公開された28元の記事 ウォン称賛14 ビュー20000 +

おすすめ

転載: blog.csdn.net/liyunxin_c_language/article/details/96970012