似乎在C ++中(或者它是一般的OOP概念?)一旦虚拟总是虚拟的事物成立。我想知道是否有它可以停止。我有这种情况需要我所要求的。
让我们说像我这样的工厂课程
class Object;
class GeneralFactory
{
private:
virtual Object* CreateObject() = 0;
};
现在我有一个专门的工厂,它仍然允许创建对象但具有更多控制权。
class SpecializedFactory : public GeneralFactory
{
private:
virtual Object* CreateObject();
virtual Object* DoCreateObject() = 0;
};
我们的想法是让SpecializedFactory::CreateObject
在其实施中使用DoCreateObject
。但事情就是这样,一个班级可以从SpecializedFactory
派生,并覆盖CreateObject
,破坏善意。
我正在寻找的是可能的,有效的,或唯一的方法是让程序员成为好公民并遵循类层次结构规则?
什么是合适的替代方案?我正在使用C ++ 03 FYI。
答案 0 :(得分:4)
您需要的是final
关键字:
struct base {
virtual void f();
};
struct derived : base {
void f() final; // virtual as it overrides base::f
};
struct mostderived : derived {
//void f(); // error: cannot override!
};
答案 1 :(得分:2)
似乎在C ++中(或者它是一般的OOP概念?)曾经是虚拟的 总是虚拟的东西。
我不会把它称为“一旦虚拟永远虚拟”,因为这听起来有点误导。虚拟性根本不是派生类的业务。虚函数都是关于 base clasess。它是需要知道函数是否为虚函数的基类,并在必要时进行虚函数调用。派生类函数可能会说“我不再是虚拟的了!”,但谁在乎呢?它已经在那时通过虚函数调用来调用。
C ++ 11 final
不会改变有关此运行时行为的任何内容,它只是在编译时阻止覆盖。
我正在寻找的是可能的,有效的,或唯一的方法 程序员是好公民,遵循阶级等级规则吗?
在C ++ 03中,最简单的方法是提供良好的文档,并在面试时只选择优秀的程序员:)
但这可能不是你想要的。这里的技术解决方案是将您的类设计更改为 has-a 关系。 使整个类最终做的解决方法存在于C ++ 03中。
所以,而不是ConcreteSpecializedFactory
是 SpecializedFactory
,而不是SpecializedFactory
has-a SpecializedFactoryImplementation
。然后你可以(可选地,为了更严格)使用friend
来允许后者仅从前者调用,并且(这是有趣部分的来源)你可以使用虚拟继承技巧3>}来自C++ FAQ "How can I set up my class so it won't be inherited from?",以使整个SpecializedFactory
课程成为最终成绩。
class SpecializedFactoryImplementation
{
public:
virtual ~SpecializedFactoryImplementation() {}
private:
SpecializedFactoryImplementation(SpecializedFactoryImplementation const &);
SpecializedFactoryImplementation &operator=(SpecializedFactoryImplementation const &);
friend class SpecializedFactory;
Object* CreateObject()
{
return DoCreateObject();
}
virtual Object* DoCreateObject() = 0;
};
class SpecializedFactoryBase
{
private:
friend class SpecializedFactory;
SpecializedFactoryBase() {}
};
class SpecializedFactory : public GeneralFactory, private virtual SpecializedFactoryBase
{
// ...
public:
SpecializedFactory(SpecializedFactoryImplementation* impl) :
m_impl(impl)
{
// null checking omitted for simplicity
}
private:
// the GeneralFactory base class should not be copyable
// anyway, so we do not have to worry about copy constructor
// or assignment operator
SpecializedFactoryImplementation* const m_impl;
virtual Object* CreateObject()
{
return m_impl->CreateObject();
}
};
以下将无法编译:
class SpecializedFactoryWrittenByEvilProgrammer : public SpecializedFactory
{
public:
SpecializedFactoryWrittenByEvilProgrammer() : SpecializedFactory(0) {}
private:
virtual Object* CreateObject()
{
return 0;
}
};
以下内容无法编译:
// somewhere outside of SpecializedFactory:
SpecializedFactoryImplementation *s;
s->CreateObject();