C++ 在C++;,如何确定类是否是继承链中的最后一个类/子类?即在基类的另一端

C++ 在C++;,如何确定类是否是继承链中的最后一个类/子类?即在基类的另一端,c++,class,inheritance,children,C++,Class,Inheritance,Children,我在简洁地表述这个问题时遇到了一些问题,但基本上,类中有一个函数可能是继承链中的最后一个类,也可能不是。在该函数中,如果类级函数是继承链中的最后一个,则将调用第二个函数。展示我所说的比解释要容易得多,因此: 假设我有Z班 Z从Y派生,Y从X派生,X从W派生 所有类都有一个名为Execute()的虚拟函数 Z.Execute()要求Y.Execute()完成,这要求X.Execute()完成,这要求W.Execute()完成 因此,Z的Execute()函数如下所示: void Z::Execut

我在简洁地表述这个问题时遇到了一些问题,但基本上,类中有一个函数可能是继承链中的最后一个类,也可能不是。在该函数中,如果类级函数是继承链中的最后一个,则将调用第二个函数。展示我所说的比解释要容易得多,因此:

假设我有Z班

Z从Y派生,Y从X派生,X从W派生

所有类都有一个名为Execute()的虚拟函数

Z.Execute()要求Y.Execute()完成,这要求X.Execute()完成,这要求W.Execute()完成

因此,Z的Execute()函数如下所示:

void Z::Execute(void)
{
   Y::Execute();

   // do Z's stuff!
   return;
}
void Y::Execute(void)
{
   X::Execute();

   // do Y's stuff!
   return;
}
类似地,Y的Execute()函数如下所示:

void Z::Execute(void)
{
   Y::Execute();

   // do Z's stuff!
   return;
}
void Y::Execute(void)
{
   X::Execute();

   // do Y's stuff!
   return;
}
等等,沿着继承链往下走

但是Y、X和W都是抽象的,因此每个都可以实例化,并且可能是也可能不是继承链中的最后一个类

这是我需要知道的。最后一个Execute()需要调用DoThisAtEndOfExecute()。DoThisAtEndOfExecute()需要在类内部调用,即它不是公共的

所以它不能在X的Execute()中,因为如果类是Y,那么调用它就太早了。它不能在Y的Execute()中,因为该类可能是Z。它不能在Z的Execute()中,因为如果该类是Y、X或W,则永远不会调用该函数

那么类有没有办法判断它是否是从继承来的呢?基本上相当于:

if (!IAmTheParentOfSomething)
   DoThisAtEndOfExecute();
这是怎么做到的?我承认,对于包含类的函数来说,更简单的方法是:

X.Execute();
X.DoThisAtEndOfExecute();

但这并不是这段代码的真正选项。

一种可能的解决方案是添加一个要执行的默认参数,并在后续调用中将该参数更改为其他值

class X{
    void Execute(bool isFinal = true);
};
//and so on.

void Z::Execute(bool isFinal)
{
   Y::Execute(false);
   // do Z's stuff!
   if(isFinal){
       // You're up!
   }
   return;
}

void Y::Execute(bool isFinal)
{
   X::Execute(false);

   // do Y's stuff!
   if(isFinal){
       // Y is the last class in this chain.
   }
   return;
}

这样,每当代码调用对象的
Execute
方法(不带参数)时,就会告诉该方法有一些外部代码正在执行它。这还允许您通过将
false
传递给该方法来防止所述终止代码被执行(如果您选择的话)。

我认为如果您将执行分为非虚拟部分和虚拟部分,则可以实现您想要的。前者将运行后者,然后调用
DoThisAtEndOfExecute
。像这样:

class X
{
public:
    void Execute()
    {
        ExecuteImpl(); //That one's virtual, the derived classes override it
        DoThisAtEndOfExecute();
    }

protected:
    virtual void ExecuteImpl()
    {
        //Whatever was in the legacy Execute
    }
}

Y和Z覆盖
ExecuteImpl()
并调用基。这样,
DoThisAtEndOfExecute()
在最派生的ExecuteImpl()版本完成后运行,而不知道实际的类

移动//do…(做…)的东西怎么样!变成一个独立的函数

class W
{
protected:
  void Stuff() { /*...*/ };
  void Finalize() { /*...*/ };
public:
  virtual ~W() {}
  virtual void Execute() { /*...*/ };
};
class X : public W
{
protected:
  void Stuff() { 
    // X Stuff
    W::Stuff();
  };
public:
  virtual ~X() {}
  virtual void Execute() { 
    X::Stuff();
    W::Finalize();
  };
};

class Y : public X
{
  void Stuff() {
    // Y Stuff
    X::Stuff();
  };
public:
  virtual ~Y() {}
  virtual void Execute() {
    Y::Stuff();
    W::Finalize();
  };
};

可以保护成员函数。这样,它只对声明类及其派生类可用。就像你想的那样,这是公共和私人之间的中间。我早就想到了。我希望有一些实际的内置功能。不幸的是,没有办法知道一个类本身是否离基类最远(至少我不知道怎么说)。但是,始终有一种方法可以让对象知道它是否被外部调用(如您所知)。我想知道你是否在这里遇到了X-Y问题?我想你和塞瓦·阿列克谢耶夫的想法是相似的。这里的区别是
Execute()
而不是
Stuff()
是虚拟的,你能解释一下你为什么走这条路吗?在所有不同的
Execute()
实现之后,基本上避免了虚拟查找,但在其他方面也做了相同的操作……我只想说明分离,以实现所需的行为。Imho非虚拟接口更可取。我会将
Execute()
公开,并对
ExecuteImpl()
进行保护,以允许堆叠。AKA“Template Method”。AKA。