Перегрузка операторов — это мощная возможность С++, и аналогично множественному наследованию имеются как ее сторонники, так и противники. На самом деле большая часть популярных языков не поддерживает ее совсем. Однако при осторожном использовании она дает возможность писать качественный и компактный код, использующий классы.
Большая часть стандартных операторов имеет несколько значений, и в общем случае вы должны следовать общепринятым соглашениям. Например, оператор << означает битовый сдвиг влево или, при работе с потоками, помещение чего-либо в поток, как здесь.
cout << "Это записывается в поток стандартного вывода.\n.";
Если вы решите перегрузить << для одного из своих классов, он должен делать одно из этих действий или, по крайней мере, аналогичное им. Перегрузка оператора — это одно, а придание им другого семантического смысла — это совсем другое. Если вы не вводите новое соглашение, повсеместно используемое в вашем приложении или библиотеке (что все равно является плохой идеей), и оно не является интуитивно понятным кому-либо еще, кроме вас, следует строго придерживаться стандартных значений.
Чтобы эффективно перегрузить операторы, требуется проделать большое количество черновой работы. Но ее требуется проделать только один раз, и она будет окупаться каждый раз, когда ваш класс будет использоваться в простых выражениях. При умеренном и разумном использовании перегрузки операторов она может сделать код легким как для чтения, так и для написания.
Рецепт 8.13.
8.15. Вызов виртуальной функции родительского класса
Требуется вызвать функцию родительского класса, но она переопределена в производном классе, так что обычный синтаксис p->method() не дает нужного результата.
Укажите полное имя вызываемого метода, включая имя родительского или базового класса (если есть только два класса, например). (См. пример 8.16.)
#include
using namespace std;
class Base {
public:
virtual void foo() {cout << "Base::foo()" << endl;}
};
class Derived : public Base {
public:
virtual void foo() {cout << "Derived::foo()" << endl;}
};
int main() {
Derived* p = new Derived();
p->foo(); // Вызов версии производного класса
p->Base::foo(); // Вызов версии базового класса
}
Регулярное использование переопределения полиморфных возможностей C++ является плохой идеей, но иногда это требуется сделать. Как и в случае с большинством других методик С++, это по большей части вопрос синтаксиса. Когда требуется вызвать определенную версию виртуальной функции базового класса, просто укажите ее имя после имени этого класса, как это сделано в примере 8.16.
p->Base::foo();
Здесь будет вызвана версия foo, определенная в Base, а не та, которая определена в каком-то из подклассов Base, на который указывает p.
Глава 9
Исключения и безопасность
9.0. Введение
Данная глава содержит рецепты по обработке исключений в С++. Язык C++ обеспечивает необходимую поддержку работы с исключениями, и, используя некоторые приемы, вы сможете создавать программный код, в котором исключительные ситуации эффективно обрабатываются и легко отлаживаются.
Первый рецепт описывает семантику C++ по выбрасыванию (throwing) и перехвату (catching) исключений и затем показывает, как создавать класс для представления исключений. Это является хорошей отправной точкой, если у вас мало или совсем нет опыта работы с исключениями. Здесь описываются также стандартные классы исключений, определенные в заголовочных файлах и .
Остальные рецепты иллюстрируют методы оптимального использования исключений и попутно вводят несколько важных терминов. Программное обеспечение не станет хорошим, если вы будете просто выбрасывать исключение, когда происходит что-нибудь неожиданное, или перехватывать исключение только для того, чтобы напечатать сообщение об ошибке и завершить программу аварийно. Для эффективного использования средств C++ по обработке исключений вам придется создавать программный код, который предотвращает утечку ресурсов и обеспечивает четкий режим работы при выбрасывании исключения. Эти условия известны как
9.1. Создание класса исключения
Требуется создать свой собственный класс исключения, предназначенный для выбрасывания и перехвата исключений.