如何跟踪(枚举)实现接口的所有类

che*_*kow 7 c++ class enumerate

我有一种情况,我有一个界面,定义某个类的行为,以填补我的程序中的某个角色,但在这个时间点,我不是100%肯定我将编写多少个类来填补该角色.但是,与此同时,我知道我希望用户能够从GUI组合/列表框中选择实现他们想要用来填充某个角色的界面的具体类.我希望GUI能够枚举所有可用的类,但是每当我决定实现一个新类来填充该角色时,我宁愿不必返回并更改旧代码(这可能是几个月之后)

我考虑过的一些事情:

  1. 使用枚举
    • 优点:
      1. 我知道该怎么做
    • 缺点
      1. 添加新类时,我将不得不更新枚举更新
      2. 难以迭代
  2. static在接口中使用某种列表对象,并在实现类的定义文件中添加新元素
    • 优点:
      1. 不必更改旧代码
    • 缺点:
      1. 甚至不确定这是否可行
      2. 不确定要存储什么样的信息,以便工厂方法可以选择正确的构造函数(可能是字符串和返回指向接口对象的指针的函数指针之间的映射)

我猜这是一个问题(或类似的问题),更有经验的程序员可能在之前(经常)遇到过,并且这种问题可能有一个共同的解决方案,这几乎肯定比任何我都好.能够想出来的.那么,我该怎么做?

(PS我搜索过,但我发现的都是这个,而且它不一样:我如何枚举所有实现通用接口的项目?看来他已经知道如何解决我想弄清楚的问题了.)

编辑:我将标题重命名为"我怎样才能跟踪......",而不仅仅是"我怎么能枚举......"因为原来的问题听起来像是我对检查运行时环境更感兴趣,我在哪里真正感兴趣的是编译时簿记.

Tim*_*imW 7

创建一个单例,您可以使用指向创建者函数的指针来注册类.在具体类的cpp文件中,您注册每个类.
像这样的东西:

class Interface;
typedef boost::function<Interface* ()> Creator;

class InterfaceRegistration
{
    typedef map<string, Creator> CreatorMap;
public:
    InterfaceRegistration& instance() {  
        static InterfaceRegistration interfaceRegistration;
        return interfaceRegistration;
    }

    bool registerInterface( const string& name, Creator creator )
    {
        return (m_interfaces[name] = creator);
    }

    list<string> names() const
    {
        list<string> nameList;  
        transform(
            m_interfaces.begin(), m_interfaces.end(), 
            back_inserter(nameList) 
            select1st<CreatorMap>::value_type>() );
    }

    Interface* create(cosnt string& name ) const 
    { 
        const CreatorMap::const_iterator it 
            = m_interfaces.find(name);  
        if( it!=m_interfaces.end() && (*it) )
        {
            return (*it)();
        }
        // throw exception ...
        return 0;
    }

private:
    CreatorMap m_interfaces;
};


// in your concrete classes cpp files
namespace {
bool registerClassX = InterfaceRegistration::instance("ClassX", boost::lambda::new_ptr<ClassX>() );
}

ClassX::ClassX() : Interface()
{
    //....
}

// in your concrete class Y cpp files
namespace {
bool registerClassY = InterfaceRegistration::instance("ClassY", boost::lambda::new_ptr<ClassY>() );
}

ClassY::ClassY() : Interface()
{
    //....
}
Run Code Online (Sandbox Code Playgroud)