2009-06-05 67 views
3

我有这样的事情:强制儿童类的静态方法重载在C++

class Base 
{ 
    public: 
    static int Lolz() 
    { 
     return 0; 
    } 
}; 

class Child : public Base 
{ 
    public: 
    int nothing; 
}; 

template <typename T> 
int Produce() 
{ 
    return T::Lolz(); 
} 

Produce<Base>(); 
Produce<Child>(); 

都返回0,这当然是正确的,但不必要的。无论如何要强制在第二个类中强制显式声明Lolz()方法,或者在使用Produce<Child>()时可能会引发编译时错误?

还是不好OO设计,我应该做一些完全不同的事情?

编辑:

什么我基本上是试图做的,就是让这样的工作:

Manager manager; 

manager.RegisterProducer(&Woot::Produce, "Woot"); 
manager.RegisterProducer(&Goop::Produce, "Goop"); 

Object obj = manager.Produce("Woot"); 

,或者更一般地说,外部抽象工厂不知道它正在生成的对象的类型,以便可以添加新的类型而无需编写更多的代码。

+0

你能提供关于上下文的细节吗?看起来像你的编程某种工厂thingy。 – diapir 2009-06-05 20:13:37

+1

如果您的Manager's Produce方法无论如何都返回一个指向基类的指针,那么使用模板有什么意义?你可以像这样定义你的RegisterProducer方法:void RegisterProducer(Object *(* pfnProduce)(),const char * pName) – 2009-06-05 20:46:25

回答

6

有两种方法可以避免它。其实,这取决于你想说什么。

(1)将Produce()作为基类的接口。

template <typename T> 
int Produce() 
{ 
    return T::Lolz(); 
} 
class Base 
{ 
    friend int Produce<Base>(); 

protected: 
    static int Lolz() 
    { 
     return 0; 
    } 
}; 

class Child : public Base 
{ 
public: 
    int nothing; 
}; 

int main(void) 
{ 
    Produce<Base>(); // Ok. 
    Produce<Child>(); // error :'Base::Lolz' : cannot access protected member declared in class 'Base' 
} 

(2)使用模板专门化。

template <typename T> 
int Produce() 
{ 
    return T::Lolz(); 
} 
class Base 
{ 
public: 
    static int Lolz() 
    { 
     return 0; 
    } 
}; 

class Child : public Base 
{ 
public: 
    int nothing; 
}; 

template<> 
int Produce<Child>() 
{ 
    throw std::bad_exception("oops!"); 
    return 0; 
} 

int main(void) 
{ 
    Produce<Base>(); // Ok. 
    Produce<Child>(); // it will throw an exception! 
} 
1

C++不支持虚拟静态功能。想想虚拟桌面必须要支持的东西,并且你会意识到它是一个不可行的选择。

2

无法在子类中重写静态方法,只能隐藏它。也没有任何东西类似于强制子类提供定义的抽象方法。如果你真的需要在不同的子类中有不同的行为,那么你应该让Lolz()成为一个实例方法,并像平常一样覆盖它。

我怀疑你在这里接近设计问题。替代原则是面向对象设计的原则之一。它基本上说,如果B是A的一个子类,那么只要你可以使用A就可以使用B。

0

据我了解你的问题,你想从父类中禁用静态方法。你可以做这样的事情在派生类:


class Child : public Base 
{ 
public: 
    int nothing; 
private: 
    using Base::Lolz; 
}; 

现在Child::Lolz变为私有。 但是,当然,修复设计要好得多:)