是否有一种方法可以防止调用派生类中的特定继承函数

Is there a way to prevent calls to a specific inherited function in a derived class?

本文关键字:派生 调用 函数 继承 一种 方法 是否      更新时间:2023-10-16

考虑以下内容:

class base {
    // base class
public:
    void doBaseStuff() {
        /* do something basic */
    }
private:
    int someDataMember;
};
class derived : public base {
    // this class inherits 'doBaseStuff()' as well as 'someDataMember'
public:
    void doDerivedStuff() {
        /* do something in addition that only this type of derived class can do */
    }
};
class specialDerived : public base {
    // say 'doBaseStuff()' doesn't make sense in the context of this class!
    // we do not want to inherit that function here
    // is there a way to prevent instances of this class from calling it?
    // we still want 'someDataMember', so we must derive from the base class
public:
    void doSpecialStuff() {
        /* do something in addition that only this special derived class can do */
    }
};

有一个类作为多个其他类的公共基类。但是,假设基类的一个成员函数不希望出现在派生类中。是否有一种方法来明确禁止继承函数在派生类?

实际上,我们可以讨论一个有1000个成员的基类,并且我们想要继承其中的999个,所以简单地放弃继承并只是复制所有代码将导致非常糟糕的代码可维护性。

使该函数在基类中成为虚函数,并在specialDerived类中提供它的虚拟实现将有效。但是如果这个函数有一个实际的返回类型,而不是void呢?然后,specialDerived类必须提供一个返回某些东西的实现。然后调用者可以假设他们得到的值是有意义的,当它实际上不是,这是一个问题。

specialDerived中简单地实现虚函数并在函数体中使用单个throw可能是一种解决方案,只要存在一些文档明确地声明在此特定派生类型的对象上调用此函数没有意义,并且此操作将抛出。我认为这是一个可能的解决方案,但我不确定这是否是最好的方法。

我假设你只是想确保该方法不是被意外调用,即当它被调用时编译错误是完美的。

您可以简单地在specialDerived中用删除的定义重写doBaseStuff:

class specialDerived : public base {
  void doBaseStuff() = delete;
public:
  void doSpecialStuff() {
      /* do something in addition that only this special derived class can do */
  }
};

这将阻止任何人使用specialDerived::doBaseStuff。仍然可以将对specialDerived的引用转换为对base的引用,并在结果上调用doBaseStuff,但如果不将doBaseStuff设置为virtual,则无法避免。

  1. 声明doBaseStuffbase中受保护
  2. base派生一个新类base2,使doBaseStuff成为public
  3. base2而不是base派生999个类
  4. base中派生一个类

一样:

class base {
protected:
    void doBaseStuff() {
        /* do something basic */
    }
private:
    int someDataMember;
};
class base2 : public base {
public:
    using base::doBaseStuff; // make it public
};
class derived : public base2 {
   // ...
};
class specialDerived : public base {
   // doBaseStuff not public here since we're derived only from base (and not base2) and didn't make it public ourself
};