Здравствуйте, mjau, Вы писали:
M>Хочется использовать эти классы в нескольких применениях (программах), причем в одном востребованы как A() так и B(), а в другом B() не используется и компилировать все реализации метода особого смысла нет. Есть ли какой-нибудь более человеческий способ исключения B() из компиляции, кроме
M>- окружения всех деклараций и реализаций B() в потомках кучкой #ifdef COMPILE_B
M>- вынесения всех реализаций B() в отдельный файл и его подключения/отключения?
Можно условно компилировать интерфейс с и без этой функции B(), а в наследниках не писать virtual. Тогда, если B() в интерфейсе отсутствует, то у наследников они будут невиртуальными функциями, нигде не использующимися (да?), и линкер их выкинет.
Ну а чтоб и компилятор не перетруждать — тут уж только ифдефить повсеместно.
Либо как-то выразить B() единообразно через другие члены наследника (т.е. воплотить паттерн Шаблонный Метод), и соответственно, ифдефить B() в промежуточном базовом классе.
Причём шаблонный метод можно сделать как на виртуальных функциях, так и на CRTP. Это уже нюансы.
// небольшое количество единообразных реализаций...
// эта пусть будет на виртуальных функциях
class CommonImpl1 : public IA
{
#ifdef COMPILE_B
private: // ибо незачем наследникам вызывать то, что может быть исключено из компиляции
virtual void B() { this->foo(); this->bar(); }
protected:
virtual void foo();
virtual void bar();
#endif
};
// а эта на CRTP
template<class T>
class CommonImpl2 : public IA
{
#ifdef COMPILE_B
private:
virtual void B() { static_cast<T*>(this)->buz(); }
};
// и куча окончательных наследников
class Derived1 : public CommonImpl1 { ..... };
class Derived2 : public CommonImpl1 { ..... };
class Derived3 : public CommonImpl2<Derived3> { ..... };
template<class T> class Derived4 : public CommonImpl2<T> { ..... }; // аналог виртуальности для CRTP :)
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>