ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ В C++ (4-Е ИЗДАНИЕ) (часть 9) онлайн
Конструкторы производного класса
Это потенциальная проблема в программе COUNTEN. Что будет, если мы захотим инициализировать значением объект класса CountDn? Сможем ли мы воспользо- ваться конструктором класса Counter с одним аргументом? Ответ будет отрица- тельным. Как мы видели в программе COUNTEN, компилятор будет использовать
конструктор базового класса без аргументов. Мы должны написать новый конст- руктор для производного класса. Это показано в программе COUNTEN2:
// counten2.cpp
// конструкторы в производных классах
#include <iostream>
using namespace std;
///////////////////////////////////////////////////////////
class Counter
{
protected: // заметьте, что тут не следует использовать private
unsigned int count; // счетчик
public:
Counter ( ) : count ( ) // конструктор без параметров
{ }
Counter ( int c ) : count ( c ) // конструктор с одним параметром
{ }
unsigned int get_count ( ) const // получение значения
{ return count; }
Counter operator++ ( ) // оператор увеличения
{ return Counter ( ++count ); }
};
///////////////////////////////////////////////////////////
class CountDn : public Counter
{
public:
CountDn ( ) : Counter ( ) // конструктор без параметров
{ }
CountDn ( int c ) : Counter ( c )// конструктор с одним параметром
{ }
CountDn operator-- ( ) // оператор уменьшения
{ return CountDn ( --count ); }
};
///////////////////////////////////////////////////////////
int main ( )
{
CountDn c1; // переменные класса CountDn
CountDn c2 ( 100 );
cout << "\nc1 = " << c1.get_count ( ); // выводим значения на экран
cout << "\nc2 = " << c2.get_count ( );
++c1; ++c1; ++c1; // увеличиваем c1
cout << "\nc1 = " << c1.get_count ( ); // показываем результат
--c2; --c2; // уменьшаем c2
cout << "c2 = " << c2.get_count ( ); // показываем результат
CountDn c3 = --c2; // создаем переменную c3 на основе c2
cout << "\nc3 = " << c3.get_count ( ); // показываем значение
cout << endl;
return 0;
}
Программа использует два новых конструктора класса CountDn. Это конст- руктор без аргументов:
CountDn ( ) : Counter ( ) { }
В этом конструкторе использована новая для нас возможность: имя функ- ции, следующее за двоеточием. Она используется конструктором класса CountDn для вызова конструктора Counter() базового класса. Когда мы запишем в функ- ции main()
CountDn c1;
компилятор создаст объект класса CountDn и вызовет конструктор класса CountDn для его инициализации. Конструктор в свою очередь вызовет конструктор клас- са Counter, который выполнит нужные действия. Конструктор CountDn() может выполнять и свои операции, кроме вызова другого конструктора, но в нашем случае это не требуется, поэтому пространство между скобками пусто.
Вызов конструктора в списке инициализации может быть лишним, но это имеет смысл. Мы хотим инициализировать поле, не важно, принадлежит оно базовому или производному классу, и перед выполнением любого оператора программы сначала будут выполнены операции конструктора.
В строке:
CountDn c2 ( 100 );
функции main() используется конструктор класса CountDn с одним аргументом. Этот конструктор вызывает соответствующий конструктор с одним аргументом из базового класса:
CountDn ( int c ) : Counter ( с ) // параметр с передается в конструктор класса Counter { }
Такая конструкция означает, что аргумент с будет передан от конструктора CountDn() в Counter(), где будет использован для инициализации объекта.
В функции main() после инициализации объектов c1 и c2 мы увеличиваем один из них и уменьшаем другой, а затем выводим результат. Конструктор с од- ним аргументом также используется в выражениях присваивания:
CountDn c3 = --c2;
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42