有没有办法阻止派生类进一步实现虚函数?

时间:2014-08-30 06:40:18

标签: c++ oop virtual-functions c++03

似乎在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。

2 个答案:

答案 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来允许后者仅从前者调用,并且(这是有趣部分的来源)你可以使用虚拟继承技巧}来自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();