我有这样的东西。
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()方法的显式声明,或者在使用Lolz()方法时抛出一个编译时错误。Produce<Child>()
?
还是说这是糟糕的OO设计,我应该做一些完全不同的事情?
EDIT:
我基本上想做的是 让这样的东西工作起来:
Manager manager;
manager.RegisterProducer(&Woot::Produce, "Woot");
manager.RegisterProducer(&Goop::Produce, "Goop");
Object obj = manager.Produce("Woot");
或者,更一般地说,一个外部的抽象工厂 它不知道它所生产的对象的类型, 这样就可以在不写更多代码的情况下增加新的类型。
有两种方法可以避免。其实,这要看你想说什么。
(1)把Produce()做成Base类的一个接口。
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!
}
在子类中没有办法重写一个静态方法,只能隐藏它。 也没有任何类似于抽象方法的东西可以强制子类提供定义。 如果你真的需要在不同的子类中采取不同的行为,那么你应该把Lolz()做成一个实例方法,然后像正常的方法一样重写它。
我怀疑你在这里接近一个设计问题。 面向对象设计的原则之一是替换原则。 它基本上是说,如果B是A的子类,那么在任何可以使用A的地方使用B都是有效的。
C++不支持虚拟静态函数。 想一想vtable必须是什么样子才能支持它,你就会意识到它是不可能的。
就我对你的问题的理解,你想从父类中禁用静态方法。你可以在派生类中做这样的事情。
class Child : public Base
{
public:
int nothing;
private:
using Base::Lolz;
};
现在... Child::Lolz
变成了private.但是,当然,修复设计会更好:)
或者在使用Produce<Child>()时抛出一个编译时错误。
现代的解决方案是使用 delete
:
class Child : public Base
{
public:
int nothing;
static int Lolz() = delete;
};
它有助于避免大量的模板,清晰地表达你的意图。