#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
может возвращать aDerived*
, а не aBase*
из-за поддержки C ковариантных возвращаемых типов, которые могут быть тем, что ищет OP…2. Я сомневаюсь в этом: вместо этого OP беспокоился о том, чтобы связать их в цепочку (так что фактический полиморфизм был причиной беспокойства). Кроме того, вы не смогли бы вернуть
Base::One()
в этом случае (без … эээ … некрасивого приведения)