我可以递归调用每个基类中的方法而无需手动输入base :: Method()吗?

时间:2016-05-16 15:48:51

标签: c++ polymorphism

内容

  • 问题
  • 实施例
  • 我为什么需要它

您好。

问题

我遇到了问题。我有一个 A 的类,其基数 B (是多态的)。在 B 类中是方法Print(),它是虚拟的。在 A 类中也是Print()。虚拟。 假设我给了一个A类型的对象(或指针),存储在B变量

B * object = new A(); 

通过致电

object->Print();

它调用A类中的方法,但我也希望它在B类中调用方法。 技术上 我想为每个孩子调用该方法,直到我到达没有孩子的课程 这可以按如下方式完成:

实施例

class A
{
   public:
      virtual void Print() const override
      {
          cout << "A" << endl;
      }
};
class B : public A
{
   public:
      virtual void Print() const override
      {
         cout << "B" << endl;
         A::Print();     // i do not want to call it here...
      }
};

问题是我确实不想被迫拨打

A::Print();

为什么

是的,你可能会问,这笔交易是什么...... 我有很长的继承链。 (假设继承链中有15-20个类)。 在游戏中,每个人都会做一些小事。

让我们说

 class GameObject
    {
       public:
          virtual void Update() const
          {
              //updates position, recounts it towards screen
          }
    };
    class Character : public GameObject
    {
       public:
          virtual void Update() const override
          {
             // Updates lives, movement
          }
    };
    class Warrior : public Character
    {
       public:
          virtual void Update() const override
          {
             // Updates armor, specific stuff
          }
    };

现在这个例子非常简单。问题是,如果我忘记添加一个调用基地:: Update()那么我很烦,为什么它不起作用。寻找这样的错误很难。我的意思是,如果有什么办法吗?

非常感谢您的回复。

度过愉快的一天

2 个答案:

答案 0 :(得分:5)

如果确实每个类都必须调用基函数,那么确保强制执行功能的一种方法是使用template pattern

class GameObject
{

   public:
      void Updater()
      {
         Update();  // this is a virtual call
         GameObject::Update(); // now call base 
      }

      virtual void Update() const
      {
      }
};

class Character : public GameObject
{
   public:
      virtual void Update() const override
      {
         // Updates lives, movement
      }
};

class Warrior : public Character
{
   public:
      virtual void Update() const override
      {
         // Updates armor, specific stuff
      }
};

class Character : public GameObject
{
   public:
      virtual void Update() const override
      {
         // Updates lives, movement
      }
};

class Warrior : public Character
{
   public:
      virtual void Update() const override
      {
         // Updates armor, specific stuff
      }
};

然后始终致电YourObject::Updater();而不是YourObject::Update()Updater函数将调用对象的Update函数,然后返回并调用基类Update

答案 1 :(得分:1)

曾经有人建议获得某个类型(N2965)的所有基础,其中gcc实际上是在<tr2/type_traits>中实现的。因此,如果可移植性不是一个问题,并且您恰好使用gcc,那么您可以像这样写一个全能:

struct A { 
    virtual ~A() = default;
    virtual void print() { print_all(*this); }    
    void print_one() { std::cout << "A\n"; }

protected:
    template <class T>
    void print_all(T& object) {
        object.print_one();
        print_all(object, typename std::tr2::bases<T>::type{});
    }   

    template <class T, class... Bases>
    void print_all(T& object, std::tr2::__reflection_typelist<Bases...> ) { 
        using swallow = int[];
        (void)swallow{0,
            (static_cast<Bases&>(object).print_one(), 0)...
        };
    }   
};

这会分割出print(),它会打印所有内容,而print_one()会打印出一种特定类型。您只需自己print()来电print_all()

struct B : A { 
    void print() override { print_all(*this); }
    void print_one() { std::cout << "B\n"; }
};

struct C : B { 
    void print() override { print_all(*this); }
    void print_one() { std::cout << "C\n"; }
};

否则,您将不得不等待其中一个反思提案被采纳。