C++ 确定哪个子类正在调用父函数

C++ Determine which child class is calling a parent function

本文关键字:调用 函数 子类 C++      更新时间:2023-10-16

好吧,所以我在任何地方都找不到答案,这是我的第一篇文章,所以请善待。基本上,如果某个子类在特定条件下调用父函数,我需要抛出异常,但另一个子类应该始终能够执行该函数。

-

-如果你想知道,这是一个账户类的提款功能,有储蓄和支票子类。储蓄有最低余额(如果提款导致其低于最低值,则抛出例外),但支票没有最低余额

class parent {
      public:
      int b;
      void A(){
             //1. Throws exception if b < # ONLY when child1 calls
             //2. Always executes code if child2 calls regardless of condition
      }              
}           

class child1 : public parent {
}
class child2 : public parent {
}

int main(){
    child1 one;
    child2 two;
    one.A();        //This needs to throw exception under certain conditions
    two.A();        //This will always execute
}

任何人都有任何提示如何确定哪个子类正在调用该函数?

没有循环依赖,就没有简单的方法可以做到这一点。可能最简单的方法是重载每个类中的函数:

class Child1 : public Parent
{
   void A(int v) 
   {
      if (this->b > v)
      {
         throw 1;
      }
      else
      {
         Parent::A(v);
      }
      return;
   }
}

您还可以在基类中使函数成为纯虚拟函数,以强制所有子级使用自己的副本覆盖该函数。

class Parent
{
   virtual void A() =0;
}
class Child1 : public Parent
{
   void A(int v) 
   {
      if (this->b > v)
      {
         throw 1;
      }
      else
      {
         <<do something>>
      }
      return;
   }
}
或者,您可以使用函子

,但这些函子可能会变得非常复杂并且需要 C++11。在这里查看它们: http://www.cprogramming.com/tutorial/functors-function-objects-in-c++.html

因为你在

基类中没有任何虚函数,所以你只是不走运。否则,您可以使用以下命令获取实际类的类型 id:typeid *this

无论如何,您的函数在基类中应该是虚拟的,在子类中应该是重写的。请记住:继承建模为IS-A关系,因此限制特定子类的服务违背了其预期用途。最好对基类具有受限行为,并在某些子类中允许更多行为。

你不想使用RTIA的地方 经常使用的一种模式是让类的枚举称之为"typeid",并为每个函数提供一个返回对象 typeid 的方法。 这将让您知道您当前正在处理的类型(通过调用 this->typeid)

但是,如果您不希望给定的类能够调用该函数,那就更容易了。重写该类中的函数并像这样执行一些操作。但是,我相信这需要虚拟函数在从通用指针使用时正常工作。

//override
return_type MyClass::MyFunction(ArgType arg)
{
    if ( !condidtionsMet ) {
        throw SomeException;
    } 
    else {
        return MyParentClass::MyFunction(arg);
    }
}

您可以尝试使用dynamic_cast

void A(){
   if(dynamic_cast<child1>() == 0) {
         //1. Throws exception if b < # ONLY when child1 calls
   }
   else             
        //2. Always executes code if child2 calls regardless of condition
   }  
}

但这是不好的做法,更好的做法是使 A() 虚函数并为 child1 和 child2 覆盖它。

class parent {
      public:
      int b;
      virtual void A() = 0;
      virtual ~parent() {}
}           

class child1 : public parent {
    virtual void A() {
    }
}
class child2 : public parent {
    virtual void A() {
    }
}

int main(){
    child1 one;
    child2 two;
    one.A();        //This needs to throw exception under certain conditions
    two.A();        //This will always execute
}