我有这样的事情:
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 :(得分:7)
有两种方法可以避免它。实际上,这取决于你想说什么。
(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!
}
答案 1 :(得分:2)
无法覆盖子类中的静态方法,只能隐藏它。也没有任何类似于强制子类提供定义的抽象方法。如果你真的需要在不同的子类中有不同的行为,那么你应该使Lolz()成为一个实例方法并正常覆盖它。
我怀疑你正在接近设计问题。面向对象设计的一个原则是替代原则。它基本上说如果B是A的子类,那么无论你在哪里使用A,它都必须是有效的。
答案 2 :(得分:1)
C ++不支持虚拟静态函数。考虑一下vtable需要支持的内容,你会意识到它是不行的。
答案 3 :(得分:0)
据我了解你的问题,你想从父类中禁用静态方法。你可以在派生类中做这样的事情:
class Child : public Base
{
public:
int nothing;
private:
using Base::Lolz;
};
现在Child::Lolz
变为私有。
但是,当然,修复设计要好得多:)
答案 4 :(得分:0)
,或者在使用Produce
时可能抛出编译时错误()
现代的解决方案是使用delete
:
class Child : public Base
{
public:
int nothing;
static int Lolz() = delete;
};
它可以避免很多样板,并清楚地表达您的意图。