2013-07-04 3 views
3

У меня есть базовый класс, который клиенты могут «закрыть»:Альтернативный шаблон дизайна для вызова функции базового класса

struct base { 
    void shutdown() { 
    //code 
    } 
}; 

Но клиенты могут (если они хотят) создать подкласс, чтобы удовлетворить свои собственные потребности:

struct der : public base { 
    void shutdown(double some, int other, bool parameters) { 
    //custom shutdown stuff 
    base::shutdown(); //<- thus MUST be called 
    } 
}; 

проблема заключается в том, что клиент должен помнить называть base::shutdown() (суперкласса создатель будет задокументировать для разработчиков подклассов). Это кажется ошибочным, поскольку ничего не применяется во время компиляции.

Есть ли альтернативные шаблоны проектирования для решения этого в некотором роде?

+0

использовать деструктор класса для выполнения «завершение». –

+0

@DavidBrown В этом смысле это не закрытие, потому что объекты должны использоваться (и будут использоваться) после их «закрытия». –

ответ

5

К сожалению, это один из тех случаев, когда вы «должны поступать правильно» при написании кода. Это относится ко многим вещам в программировании. Если вы не делаете правильных вычислений при расчете чего-то, это тоже неправильно. Или если вы вызываете функцию дважды, которую нужно вызывать только один раз. Или не называть его вообще, когда он должен быть вызван. Все эти вещи «делают это неправильно». Вы не можете помешать программистам совершать ошибки ...

Конечно, если бы вы не добавили кучу дополнительных параметров, вы могли бы сделать это «в обратном порядке», имея не виртуальную функцию в базовом режиме, класс, который не переопределяется, а затем пусть базовый класс вызывает функцию virtual в производном классе. Как я уже сказал, это не сработает, если у вас есть параметры, которых нет в базовом классе, которые должны войти в производный класс.

Пример того, что я имею в виду:

struct base { 
    void shutdown() final { // final: it can't be overridden in derived class 
    do_shutdown(); // Calls derived function's 
    // ... more code here ... 
    } 
    virtual void do_shutdown() { } // default is "do nothing". 
}; 


struct der: public base 
{ 
    // not overriding `shutdown`, but overriding `do_shutdown` 
    void do_shutdown() 
    { 
     .. some code goes here .. 
    } 
} 

Теперь вызов der->shutdown() будет вызывать реализацию базового класса, которая вызывает do_shutdown в производном классе до полного завершения в базовом класса shutdown.

Однако, как я уже сказал, вы не можете добавлять дополнительные параметры, когда вы это делаете - на самом деле получение класса и изменение параметров является «неправильным» - не так уж неправильно, вы не можете этого делать, но он имеет тенденцию быть плохой при использовании полиморфизма наследования, поскольку вся цель полиморфизма заключается в том, что существует некоторый общий код, который «не знает, является ли это объектом базового класса, производным1 или объектом производным2», поэтому, если он должен знать, какой тип объекта передать правильное количество аргументов, он становится немного бессмысленным.

+0

Вы должны сделать 'shutdown() final' или подклассы все равно могут переопределить его напрямую. –

+0

@YohanDanvin: Хорошая точка. –

2

Я бы не стал беспокоиться об этом. Это похоже на оператор присваивания производных классов. Это не ваша ошибка, если разработчик подкласса забывает его вызывать, но это не ошибка, если это не так.

C++ FAQ entry on the subject

Смежные вопросы