我在C ++中有以下类层次结构:

class Base {
    virtual void apply() = 0;
};

class Derived : public Base {
    virtual void apply() {
        // implementation here that uses derived_specialty
    }

    virtual void derived_specialty() = 0;
};


class Implementation : public Derived {   
    virtual void derived_specialty() {
        // implementation
    }
};

我想保证实施级别的课程不会提供自己的应用程序实施,并且他们只能实施derived_specialty。是否有任何方法可以保证从派生中继承的类不会实现应用程序,以便使用派生::应用程序实现?我的理解是,在C ++中,一种在基类中虚拟的方法是虚拟的,直到继承层次结构,但是如果C ++中有任何技巧可以完成,我将有兴趣听到有关它们的消息。

我总是对C ++允许的事情感到惊讶,因此我认为值得一提的是。 :)

有帮助吗?

解决方案

您可以通过构图做到这一点:

class Base {
    virtual void apply();
};

class Derived : public Base {

    class IImplementation {
        virtual void derived_specialty() = 0;
    };

    IImplementation& m_implementation;

    Derived(IImplementation& implementation)
        : m_implementation(implementation)
    {}

    virtual void apply() {
        // implementation here that uses m_implementation.derived_specialty
    }

};


class Implementation : Derived::IImplementation {   
    virtual void derived_specialty() {
        // implementation
    }
};

其他类仍然可以派生并覆盖应用方法,但是您的实现类不再是这些类别之一。

其他提示

您可以使实施成为代表类,而不是派生的专业化

class Derived : public Base
{
    Derived()

    void apply() 
    {
        //whatever, delegate to impl class instance
        impl->apply_specialization();
    }


    Impl* impl;
};

class Impl : public WhateverImplInterface
{
      void apply_specialization(){}
};

然后,实现无法访问应用功能,并且与层次结构分开。然后,通过IMPH类的实例对派生类进行参数化。

在您的文档中明确限制。

“我想保证实施级别的课程不会提供自己的申请实施。”

你不能。

到目前为止,我所看到的示例都没有阻止任何派生类定义自己的应用功能。他们都提供了建模应用和派生之间关系的方法,向用户暗示他们 不应该 替代申请。但是,您可以在文档线中实现同样的目标。

您正在寻找的是C ++中不存在的Java最终声明,对吗?

您可以使基础::应用非虚拟元素,并在基础内也使用模板方法模式。

本文解释了这种做法的优势:
http://www.gotw.ca/publications/mill18.htm

您可以在攻击方中提出断言以确保 申请 没有被覆盖:

class Base {
    virtual void apply() = 0;
};

class Derived : public Base {
    virtual void apply() {
        // implementation here that uses derived_specialty
    }
    virtual ~Derived() {
        assert(this->apply == Derived::apply);
    }
    virtual void derived_specialty() = 0;
};


class Implementation : public Derived {   
    virtual void derived_specialty() {
        // implementation
    }
};

这里的想法是,> apply将在派生时从虚拟表中获取方法地址,:: apply apply在编译时间内解决了解决方案。如果它们是平等的,则在实施类中不会再次申请。这种方法还具有一个优势,即它在发行版中没有施加性能惩罚,在该版本中,sostert()宏应(应该)从生成的代码中剥离。

尝试使用模板方法模式

维基百科 有一个C ++示例。

它不会改变封装,但可以改进设计,因此您不需要。

总是有访问修饰符:

 class base {
      protected: virtual void real_apply() = 0;
 };
 class derived : public base {
      void real_apply();
 public:
      apply() { real_apply(); }
 };
 class other : public derived {
      void func() {
          apply();      // this is ok
          real_apply(); // this is a compile time error
      }
 };
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top