在C ++中以静态方式将变量实例绑定到类中?

时间:2010-04-20 16:03:21

标签: c++

所以我有一个基于插件的系统,我正在编写。用户可以创建Plugin类的子类,然后在运行时加载它并与系统的其余部分集成。当从系统运行插件时,它在一组插件的上下文中运行,我称之为Session。

我的问题是在用户插件中,有两个名为pf_ostream和pf_istream的流类可用于向系统读/写数据。我想以某种方式将插件实例的会话变量绑定到pf_ostream和pf_istream,以便当用户实例化这些类时,它已经绑定到它们的会话(基本上我不希望它们看到会话内部)

我可以用宏执行此操作,包含对构造函数的调用,如:

#define MAKE_OSTREAM = pf_ostream_int(this->session)

但我认为可能有更好的方法。我看了在Plugin包装pf_ostream中使用嵌套类,但看起来嵌套类不能以闭包方式访问封闭类变量。

有没有人知道这样做的好方法?

3 个答案:

答案 0 :(得分:1)

这是基于您在其中一条评论中提到的工厂理念的另一个答案。它使用Facade模式将系统工具的创建集中在绑定到System的{​​{1}}类中:

Session

如果您有许多系统工具,则应明智地使用前向声明以避免长编译时间。此解决方案的缺点是将系统设施集中在依赖关系“焦点”(#include <boost/shared_ptr.hpp> class System { public: typedef boost::shared_ptr<pf_ostream> pf_ostream_ptr; typedef boost::shared_ptr<pf_istream> pf_istream_ptr; // Other system facilities... System(Session* session) : session_(session) {} pf_ostream_ptr makeOstream() {return pf_ostream_ptr(new pf_ostream(session_));} pf_istream_ptr makeIstream() {return pf_istream_ptr(new pf_istream(session_));} private: Session* session_; }; class Plugin { public: Plugin(System* system) : system_(system) {} System& system() {return *system_;} private: System* system_; }; class MyPlugin : public Plugin { public: MyPlugin(System* system) : Plugin(system) {} void print() { pf_ostream_ptr pfos( system().makeOstream() ); *pfos << "Hello World!\n"; // pfos will be deleted automatically at the end of this scope } }; 类)中。如果System类在另一个使用更多或更少系统工具的应用程序中重用,则可能需要更改它。

修改

以下是如何应用代理模式(以及Pimpl习惯用法)来获取具有值语义的引用计数流类:

System

用户必须知道代理对象的副本将引用相同的实际流。希望这会有所帮助。

答案 1 :(得分:0)

您可以在构造过程中为嵌套类提供对其父类的引用。

class plugin_base {
protected:
   plugin_base(): _istream(*this) {}
   class istream {
   public:
      istream(plugin_base& p): _plugin(p) {}
      ...
   private:
      plugin_base& _plugin;
   };
   istream _istream;
};

class plugin: public plugin_base {
   ...
};

每次实例化它的子类时,编译器都会自动调用plugin_base的构造函数。

答案 2 :(得分:0)

可以使用具有Session的事物的接口类。这里有一些值得深思的东西:

class IContext
{
public:
    virtual ~IContext() {}
    virtual Session* session() = 0;
};


class Plugin : public IContext
{
public:
    Plugin(Session* session) : session_(session) {}
    virtual ~Plugin() {}
    virtual Session* session() {return session_;}

protected:
    Session* session_;
};


class MyPlugin : public Plugin
{
public:
    MyPlugin(Session* session) : Plugin(session) {}
    virtual ~MyPlugin() {}
    void print()
    {
        pf_ostream pfos(this);
        pfos << "Hello world!\n";
    }
};


class pf_ostream
{
public:
    pf_ostream(IContext* context) : session_(context->session()) {}
    // ...

private:
    Session* session_;
    // ...
};

请注意插件编写者现在如何使用pf_ostream pfos(this)代替pf_ostream pfos(this->session),现在忘记了Sessionpf_ostream也忽略了Plugin及其后代。

IContext可能不是这里最好的名字。也许IHasSession? (IHasCheezburger ???)