c++在具体类中强制方法重写

C++ Forcing Method Override In Concrete Class

本文关键字:方法 重写 c++      更新时间:2023-10-16

是否有一种方法在c++中编写一个具体类,当另一个类从它派生时,有一个必须被重写的方法。抽象类允许强制派生类创建任何抽象方法的具体版本,但我想要的是一个基类,它可以强制这样做,但也可以在自己的权利中使用。我知道抽象方法也可以指定默认功能,但这仍然是一个不能实例化的抽象类。

我也看了模板方法模式,但这似乎不是我正在寻找的。

我将假设您正在寻找执行此条件的编译时(感谢@Chad指出这一点)

据我所知,c++中没有直接的语言机制。我的意思是,没有一个保留关键字放在你的方法声明前面来实现你想要的目标。

我认为你所说的指向了你们软件中的一个设计问题。假设您想强制foo()方法由以下代码片段

中的所有继承类重新实现
class BaseButConcrete
{
    ... //Common stuff
    ... //
    virtual void foo()
    { /*implementation that you do not want to be inherited, but will be...*/ }
}
class DerivedOtherConcrete : public BaseButConcrete
{
    void foo()
    { /*different implementation, 
      but no obligation from compiler point of view*/ }
}

我看不出为什么所有常见的东西不能在抽象基类中移动的好的设计理由。从你所描述的,你不想继承foo在派生的实现,所以不要继承那部分!因此,非常经典的设计应该做到这一点:

class AbstractBase
{
    ... //Common stuff has moved here
    ... //
    virtual void foo() =0;
}
class NotAnymoreBaseButStillConcrete : public AbstractBase
{
    void foo()
    { /*implementation that should not be inherited,
      and that will not by design*/ }
}
class DerivedOtherConcrete : public AbstractBase
{
    void foo()
    { /*different implementation, 
      now mandatory compiler-wise for the class to be concrete*/ }
}

这样,公共的东西仍然在你所有的派生类之间共享,你保留你不想继承的东西(即foo实现)在不同继承路径的类中分开。

不,不可能。如果你想强制(在编译时)一个派生类定义一个虚函数,那么它的基类需要是抽象的,或者换句话说,基类需要有一个纯虚函数。抽象类(带有纯虚函数)不能是具体的,也就是说,你不能实例化它。

一种选择是将类的所有实现放入抽象超类中,并从该超类继承。

  • 将所有具体类T的实现移到抽象类s中。
  • 在S中,让必须被重写的方法成为一个纯虚函数——并提供它的定义。
  • T子类S.
  • 在T中,重写必须被重写的函数,并调用S实现。
  • 将T子类改为s子类
  • 防止t子类化

比起定义中间类,我发现对多重继承的利用更加直观和干净。如果我们的派生类也继承了一个抽象类,该抽象类声明了一个纯虚方法,其名称与我们想要强制重写的方法相同,则编译器将不允许实例化派生类型的对象,除非该方法在派生类中实际被重写。

#include <iostream>
struct Base{
  virtual void print() {std::cout << "Base" << std::endl; }  
};
struct RequireOverride {
  virtual void print() = 0;   
};
struct D1: Base, RequireOverride {
  virtual void print() {std::cout << "D1" << std::endl; }  
};
struct D2: Base, RequireOverride {
  // no override of function print() results in a compilation error
  // when trying to instantiate D2
};

int main() {
  D1 d1;
  d1.print(); //ok

  //D2 d2; // ERROR: cannot declare variable 'd2' to be of abstract type 'D2'
           // because the following virtual functions are pure within 'D2':
           // virtual void RequireOverride::print()
  return 0;
}

如果你有多个方法,你想要强制覆盖的存在,那么你可以把它们都放在RequireOverride中,或者定义更多的结构来多重继承,比如RequireOverrideMethod1, RequireOverrideMethod2,根据上下文。

正如其他人所提到的,你可以"修复";通过将当前的具体类拆分为抽象类和具体类,可以实现一级派生。

这种方法的常见概括是必须使用类模板从每个抽象类创建具体类。例如,它可以提供一个clone方法。或者,在微软的ATL中,它提供IUnknown接口实现。

然而,具有自动生成的具体叶的抽象类层次结构通常是太多的工作和复杂性。实际的方法是只记录必须覆盖的内容,如clone。一般来说,你不能强迫别人的代码是正确的,你只能在这个方向上帮助它。

顺便说一下,如果你能更具体地说明你的问题,那么可能会有比这种笼统的愿望更好的答案。然而,通过概括你的问题,你概括了答案。