воскресенье, 1 сентября 2013 г.

Перегрузка функций в иерархиях классов

Имена в производных классах скрывают имена из базовых классов,  т.к. область видимости производного класса является вложенной для области базового класса. Если в базовом классе перегружена функция, то функция с таким же именем в производном классе скрывает весь перегруженный набор функций базового класса для данного имени.
Причина: не позволяет случайно унаследовать перегруженные функции всех базовых классов.

Чтобы сделать скрытые имена видимыми:
- используйте using-объявления: если вы наследуете базовому классу с перегруженными функциями и хотите переопределить только некоторые из них, то должны включить using-объявление для каждого имени, иначе оно будет скрыто.

- перенаправляющие функции: определение новой функции, из которой вызывается функция базового класса.

Пример:

class Base
{
private:
            int x;
public:
            virtual void mf1() = 0;
            virtual void mf1(int);
            virtual void mf2();
            void mf3();
            void mf3(double);
            //...
};
class Derived: public Base
{
public:
            virtual void mf1();
            void mf3();
            void mf4();
            //...
};

Derived d;
int x;
//...
d.mf1(); // правильно, вызывается Derived::mf1
d.mf1(x); // ошибка! Derived::mf1 скрывает Base::mf1
d.mf2(); // правильно, вызывается Base::mf2
d.mf3(); // правильно, вызывается Derived::mf3
d.mf3(x); // ошибка! Derived::mf3 скрывает Base::mf3

Решение: используем using- включение имени базового класса.

class Base
{
private:
            int x;
public:
            virtual void mf1() = 0;
            virtual void mf1(int);
            virtual void mf2();
            void mf3();
            void mf3(double);
            //...
};
class Derived: public Base
{
public:
            using Base::mf1; // обеспечить видимость всех (открытых) имен
            using Base::mf3; // mf1 и mf3 из класса Base в классе Derived
            virtual void mf1()
            void mf3();
            void mf4();
            //...
};

Derived d;
int x;
//...
d.mf1(); // по-прежнему правильно, вызывается Derived::mf1
d.mf1(x); // теперь правильно, вызывается Base::mf1
d.mf2(); // по-прежнему правильно, вызывается Base::mf2
d.mf3(); // по-прежнему правильно, вызывается Derived::mf3
d.mf3(x); // теперь правильно, вызывается Base::mf3


Источник: Скотт Мэйерс Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ.
По мотивам правила 33.



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

Отправить комментарий