Вызов цепочки функций на разных уровнях наследования классов

#c #method-chaining

#c #метод-объединение в цепочку

Вопрос:

Учитывая:

 class Foo {
 public:
   void Method1();
}
class Bar extends Foo {
 public:
   Bar* Method2();
}
class Baz extends Bar {
 public:
   Baz* Method3();
}
  

Итак,

 someObject *b = new Baz();
b->Method3()->Method2()->Method1();
  

Это будет работать, поскольку Baz() содержит все методы, включая Method2() , Bar contains Method1() ;

Но из-за возвращаемого типа это кажется плохой идеей — при обращении к более простым Method1() на первом уровне наследования перед вызовом более сложных Method3() , и при необходимости сохранять эти вызовы в одной строке..

 b->Method1()->Method2()->Method(3); // will not work?
  

Кроме того, кто-то сказал мне, что помещение try.. catch.. throw внутрь одной из них Method's иногда приводит к завершению цепочки без вызова метода next с неправильным значением. Это правда?

Итак, как правильно реализовать цепочку методов в C ?

Комментарии:

1. Кстати, это недопустимый синтаксис C .

2. Ищи CRTP и рыдай. Он предоставляет ту же функциональность без virtual методов, но его намного сложнее реализовать.

3. @CodeAngry каким-то образом это было включено habrahabr.ru в тот же день, когда вы упомянули об этом здесь..

4. @kagali-san Примерно каждый год я гуглю, чтобы посмотреть, не появляется ли новый метод, более простой, чем CRTP, не-виртуальных функций. И каждый год я возвращаюсь к CRTP. 🙂

Ответ №1:

Для этого и существуют виртуальные методы. Судя по синтаксическим ошибкам, вы новичок в C

 struct Base
{
    virtual Base* One() { return this; };
    void TemplateMethod() { this->One(); }
};

struct Derived : public Base
{
    virtual Base* One() { /* do something */ return Base::One(); }
};
  

Когда вы вызываете TemplateMethod:

 int main() 
{ 

      Base* d = new Derived();
      d->TemplateMethod(); // *will* call Derived::One() because it's virtual

      delete d;

      return 0;
}
  

Комментарии:

1. Обратите внимание, что Derived::One может возвращать a Derived* , а не a Base* из-за поддержки C ковариантных возвращаемых типов, которые могут быть тем, что ищет OP…

2. Я сомневаюсь в этом: вместо этого OP беспокоился о том, чтобы связать их в цепочку (так что фактический полиморфизм был причиной беспокойства). Кроме того, вы не смогли бы вернуть Base::One() в этом случае (без … эээ … некрасивого приведения)