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