似乎在C ++中(或者是通用的OOP概念?),曾经的虚拟总是虚拟的东西成立了。我想知道是否可以将其停止。我有这种情况需要我的要求。

假设我有一个像这样的Factory类

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。

最佳答案

似乎在C ++中(或者是通用的OOP概念?)
  总是虚拟的东西。


我不会称其为“一次虚拟总是虚拟”,因为这听起来有点误导。虚拟性根本不是派生类的事。虚拟功能全都与基本情况有关。它是基类,需要知道一个函数是否为虚函数,并在必要时进行虚函数调用。派生类函数可能会说“我不再是虚拟的!”,但是谁在乎呢?此时已经通过虚拟函数调用来调用它。

C ++ 11 final不会对此运行时行为进行任何更改,只是防止在编译时进行覆盖。


  我在寻找的是可能的,有效的方法,还是唯一的方法是
  程序员要成为好公民并遵循班级等级规则?


在C ++ 03中,最简单的方法是编写好的文档,并在面试时只选择优秀的程序员:)

但这可能不是您想要的。这里的一个技术解决方案是将您的班级设计更改为“拥有”关系。在C ++ 03中确实存在使整个类最终化的解决方法。

因此,使ConcreteSpecializedFactory具有-a SpecializedFactory而不是SpecializedFactory是-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();

10-08 19:14