C++ 几个C++;类需要在不同的实现中使用相同的静态方法

C++ 几个C++;类需要在不同的实现中使用相同的静态方法,c++,design-patterns,C++,Design Patterns,我需要几个C++类来拥有一个静态方法“登记”,但是登记的实现在这些类之间有所不同。p> 它应该是静态的,因为我的想法是用Lua“注册”所有这些类(当然只有一次) 显然,我不能用静态纯虚函数声明接口。你们建议我做什么?简单是受欢迎的,但我认为某种模板可以工作 我希望实现的目标的示例 class registerInterface { public: static virtual void register() = 0; //obviously illegal }; class someC

我需要几个C++类来拥有一个静态方法“登记”,但是登记的实现在这些类之间有所不同。p> 它应该是静态的,因为我的想法是用Lua“注册”所有这些类(当然只有一次)

显然,我不能用静态纯虚函数声明接口。你们建议我做什么?简单是受欢迎的,但我认为某种模板可以工作

我希望实现的目标的示例

class registerInterface
{
public:
    static virtual void register() = 0; //obviously illegal
};

class someClass: public registerInterface
{
    static virtual void register()
    {
        //I register myself with Lua
    }
}

class someOtherClass: public registerInterface
{
    static virtual void register()
    {
        //I register myself with Lua in a different way

    }
}

int main()
{
    someClass::register();
    someOtherClass::register();

    return 0;
}

基于您对问题的描述,我不清楚您为什么需要类上的“虚拟静态方法”。这应该是完全合法的

class SomeClass {
  static void register(void) {
    ...
  }
}

class SomeOtherClass {
  static void register(void) {
    ...
  }
}

int main(int argc, char* argv[]) {
  SomeClass::register();
  SomeOtherClass::register();

  return 0;
}

放下RegisterInterface,我想你不需要它。

如果有用的话,你可以接受Hitesh的答案,并添加:

struct luaRegisterManager {
    template <typename T>
    void registrate() {
        T::registrate();
        // do something else to record the fact that we've registered - 
        // perhaps "registrate" should be returning some object to help with that
    }
};
如果您试图将此代码拆分到多个编译单元,则会出现各种各样的问题。此外,这种情况会导致内存泄漏检测器的虚假报告,除非您还编写了一些代码来在最后删除所有内容,或者使用
共享的ptr
向量、Boost指针向量等。但是您可以看到一个类可以“注册自身”,并且您需要一个对象来进行虚拟调用


在C++中,通常你会尝试避免静态初始化,但是在程序开始时支持某种设置/依赖注入。因此,通常您只需列出您关心的所有类(对每个类调用一个函数),而不是尝试自动执行此操作。

您的意图是高尚的,但您的解决方案是“过度工程化”(除非我缺少一个明显的解决方案)

这里有一种可能性:你可以用

class RegisterInterface{
   friend void register(RegisterInterface* x){x->do_real_register();}
 protected:
   virtual void do_real_register();
}

class Foo : public RegisterInterface{
 protected:
  virtual void do_real_register(){}
};

class Bar : public RegisterInterface{
 protected:
  virtual void do_real_register(){}
};

int main(int argc, char* argv[]) {
  BOOST_FOREACH(RegisterInterface* ri, registered_interfaces)
  {
    register(ri);
  }
  return 0;
}

这样怎么样?定义接口类:

// IFoobar.h
class IFoobar{
    public:
        virtual void Register(void) = 0;
}
然后定义处理寄存器的类

// RegisterFoobar.h
class RegisterFoobar{
    public:
        // Constructors etc...
        IFoobar* fooBar;
        static void RegisterFoobar(IFoobar&  fubar){
             foobar = &fubar;
        }
    private:
        void Raise(void){ foobar->Register(); }
}
现在,定义另一个类似这样的类

// MyFuBar.h
class MyFuBar : IFoobar{
    public:
        // Constructors etc...
        void Register(void);
    private:
        RegisterFoobar* _regFoobar;
}
按如下方式调用代码:

//MyFuBar.cpp
MyFuBar::MyFuBar(){
    _regFoobar = new Foobar();
    _regFoobar->RegisterFoobar(this);
}
void MyFuBar::Register(void){
    // Raised here...
}

也许我误解了你的要求…

我知道你已经接受了答案,但我想我还是会写下来的。如果使用一些静态初始化和CRTP,则可以拥有自注册类:

#include <vector>
#include <iostream>

using namespace std;

class RegisterableRoot // Holds the list of functions to call, doesn't actually need
                       // need to be a class, could just be a collection of globals
{
  public:
  typedef void (*registration_func)();
  protected:
  static std::vector<registration_func> s_registery;
  public:
  static void do_registration()
  {
    for(int i = 0; i < s_registery.size(); ++i)
      s_registery[i]();
  }
  static bool add_func(registration_func func) // returns something so we can use it in
                                               // in an initializer
  {
     s_registery.push_back(func);
     return true;
  }
};



template<typename RegisterableType>          // Doesn't really need to inherit from
class Registerable : public RegisterableRoot // RegisterableRoot
{
   protected:
   static const bool s_effect;
};


class A : public Registerable<A> // Honestly, neither does A need to inherit from 
                                 // Registerable<T>
{
   public:
   static void Register()
   {
     cout << "A" << endl;
   }
};

class B : public Registerable<B>
{
   public:
   static void Register()
   {
     cout << "B" << endl;
   }
};

int main()
{

  RegisterableRoot::do_registration();
  return 0;
}


std::vector<RegisterableRoot::registration_func> RegisterableRoot::s_registery;

template <typename RegisterableType> // This is the "cute" part, we initialize the 
                                     // static s_effect so we build the list "magically"
const bool Registerable<RegisterableType>::s_effect = add_func(&RegisterableType::Register);

template class Registerable<A>; // Explicitly instantiate the template
                                // causes the equivalent of
                                // s_registery.push_back(&A::Register) to
                                // be executed
template class Registerable<B>;

虽然如果我是你,我不会相信这个命令。请注意,
模板类Registerable
不必与do\u注册调用位于同一个翻译单元中,您可以将其与
Foo
的其余定义放在一起。如果您从
Registerable
继承,并且没有为您的类编写
static void Register()
函数,那么您将得到一个编译器错误(当然可能是神秘的),这与您在真的存在“静态虚拟”时所预期的非常相似。“magic”只是将特定于类的函数添加到要调用的列表中,这避免了在静态初始值设定项中进行实际注册的一些陷阱。你仍然需要调用
do\u registration
,以备不时之需。

我考虑过这一点,但从设计角度来看,这并不太好。让我们把它变得更复杂一点,我想让一个“lua注册管理器”知道应该向lua注册的每种类型的类(因此,大体上,我可以“为每个注册的类,class::register(),使用多态性”)@从一个设计的角度选择一个更好的语言;-)类不是C++中的第一类对象,它们不表现多态性(一个实例是一个RealStCurror接口的实例,但是MeCaskLs本身没有一个与RealStor接口本身类型相关的类型)C++类不是一个可以被放入集合中并迭代的一流对象。C++不是面向对象的,比如说露比或Objtovi-C,在那里你可以收集和迭代方法调用的类对象集合。那么,没有更好的方法来实现它了吗?Gando:我怀疑不是你对“好”的定义。但是我仍然不清楚你想要达到什么,所以我不能给你提供一个C++的方式来评估它的正确性。好吧,你的答案非常好。所以在最后一个例子中,你静态地注册了那些类(主)。,然后迭代注册类的向量。我可以看出这实际上会导致问题,应该避免。您对Hitesh答案的附加内容也非常受欢迎,我认为这是我最终将使用的内容。非常感谢。@Mr.Gando:我现在增强了我的静态注册代码,以减少使用的样板文件数量当然,这不会影响静态初始化的基本问题。同时,我的编译器提醒我,我们不能有一个名为“register”的函数“-这是一个关键词。我一直在做这样的事情。我添加了一个register类,它跟踪工厂对象的全局实例中的可注册项。注册器是在第一次使用时构造的(在静态注册器::instance()函数中)。通过在这些类中重载“new”和“delete”以使用特定堆的一组函数(为了简单起见,malloc()、free()封装在特定的DLL中),可以避免跨DLL边界执行此操作时出现问题等。“unload”函数将减少假内存泄漏消息,但您可能仍然错误地检测到全局工厂对象的泄漏。我非常喜欢您的静态注册码。真的不推荐吗?我的意思是,我认为这可以给我很大的灵活性,并将我/其他开发人员忘记注册某个类X,然后出现意外行为/错误的风险降至最低。Globals有些不受欢迎,但在安装后不会修改,所以也不太坏。问题是全局变量的动态初始化。参见规范中的3.6.2/3:“实现定义了命名空间对象的动态初始化与否
//MyFuBar.cpp
MyFuBar::MyFuBar(){
    _regFoobar = new Foobar();
    _regFoobar->RegisterFoobar(this);
}
void MyFuBar::Register(void){
    // Raised here...
}
#include <vector>
#include <iostream>

using namespace std;

class RegisterableRoot // Holds the list of functions to call, doesn't actually need
                       // need to be a class, could just be a collection of globals
{
  public:
  typedef void (*registration_func)();
  protected:
  static std::vector<registration_func> s_registery;
  public:
  static void do_registration()
  {
    for(int i = 0; i < s_registery.size(); ++i)
      s_registery[i]();
  }
  static bool add_func(registration_func func) // returns something so we can use it in
                                               // in an initializer
  {
     s_registery.push_back(func);
     return true;
  }
};



template<typename RegisterableType>          // Doesn't really need to inherit from
class Registerable : public RegisterableRoot // RegisterableRoot
{
   protected:
   static const bool s_effect;
};


class A : public Registerable<A> // Honestly, neither does A need to inherit from 
                                 // Registerable<T>
{
   public:
   static void Register()
   {
     cout << "A" << endl;
   }
};

class B : public Registerable<B>
{
   public:
   static void Register()
   {
     cout << "B" << endl;
   }
};

int main()
{

  RegisterableRoot::do_registration();
  return 0;
}


std::vector<RegisterableRoot::registration_func> RegisterableRoot::s_registery;

template <typename RegisterableType> // This is the "cute" part, we initialize the 
                                     // static s_effect so we build the list "magically"
const bool Registerable<RegisterableType>::s_effect = add_func(&RegisterableType::Register);

template class Registerable<A>; // Explicitly instantiate the template
                                // causes the equivalent of
                                // s_registery.push_back(&A::Register) to
                                // be executed
template class Registerable<B>;
 A
 B