
техпрог / Comp-Sci-02
.pdf
Материалы к лекции 2.
Объектно-ориентированное программирование
В классе объединены данные и функции управления этими данными. Такое объединение называется инкапсуляцией.
Размещение данных в разделе private называют сокрытием данных.
А как в Википедии.
Инкапсуляция— это принцип, согласно которому любой класс должен рассматриваться как чѐрный ящик— пользователь класса должен видеть и использовать только интерфейсную часть класса (т. е. список декларируемых свойств и методов класса) и не вникать в его внутреннюю реализацию. Поэтому данные принято инкапсулировать в классе таким образом, чтобы доступ к ним по чтению или записи осуществлялся не напрямую, а с помощью методов. Принцип инкапсуляции (теоретически) позволяет минимизировать число связей между классами и, соответственно, упростить независимую реализацию и модификацию классов.
Сокрытие данных— неотделимая часть ООП, управляющая областями видимости. Является логическим продолжением инкапсуляции. Целью сокрытия является невозможность для пользователя узнать или испортить внутреннее состояние объекта.
Из Г.Буч. ―Объектно-ориентированный анализ и проектирование с примерами приложений на С++‖:
―Чаще всего инкапсуляция выполняется посредством скрытия информации, то есть маскировкой всех внутренних деталей, не влияющих на внешнее поведение. Обычно скрываются и внутренняя структура объекта и реализация его методов.‖
Инкапсуляция скрывает детали реализации объекта. (Г. Буч, стр. 63)

Пример 1. Реализация функций-членов вне класса. Используется операция ―::‖ (операция доступа к компоненте класса)
#include <iostream> using namespace std; class Cdrom{
int speed;//скорость int year;// год выпуска
public:
void set_speed(int s); int get_speed();
void set_year(int y); int get_year();
};
void Cdrom::set_speed(int s)
{speed=s;
}
inline int Cdrom::get_speed()
{return speed;
}
void Cdrom::set_year(int y)
{ |
year=y; |
|
} |
|
|
int Cdrom::get_year(){ |
return year; |
|
} |
|
|
int main() |
|
{Cdrom acer;
acer.set_speed(40); acer.set_year(2006); cout<<"\nCd-Rom Acer "<<acer.get_speed(); cout<<" god vypuska "<<acer.get_year(); return 0;
}
Обратите внимание на
inline int Cdrom::get_speed() { return speed;
}
Конструкторы и Деструкторы
Конструктор вызывается каждый раз, когда создаѐтся объект данного типа; деструктор – при уничтожении. При преобразованиях типов с участием экземпляров классов тоже вызываются конструкторы и деструкторы.
Пример 2. Конструктор класса. Имя конструктора совпадает с именем класса.
#include <iostream> using namespace std;
class Cdrom{
int speed; int year;
public:
Cdrom(int s,int y){speed=s;year=y;}

void set_speed(int s) {speed=s;} int get_speed() {return speed;} void set_year(int y){year=y;} int get_year(){return year;}
};
int main()
{Cdrom acer(40,2006);
Cdrom sony;// Это уже ошибка cout<<"\nCd-Rom Acer "<<acer.get_speed();
cout<<" god vypuska "<<acer.get_year(); return 0;
}
Создание объекта в C++ всегда сопровождается вызовом конструктора. Если класс совсем не содержит конструкторов (как в примере 1), то система создаѐт конструктор по умолчанию.
Cdrom acer;
– это вызов конструктора по умолчанию.
Нужно запомнить, что компилятор создает конструктор, заданный по умолчанию, только пока в классе нет конструкторов. После включения в класс конструктора, компилятор уже не создаст конструктор по умолчанию и это уже задача программиста. В примере 2 можем создавать объекты только так
Cdrom acer(40,2006);
т.е. указывая аргументы. В этом примере уже не можем создать объект, просто указав его имя
Cdrom sony;
Пример 3. Конструктор объявлен явно, поэтому у класса нет конструктора по умолчанию, подставляемого системой.
#include <iostream> using namespace std; class Cdrom{
int speed;//скорость int year;// год выпуска
public:
Cdrom(int s,int y=2004){speed=s;year=y;cout<<"\nConstr-2";} void set_speed(int s){speed=s;}
int get_speed(){return speed;}
void set_year(int y){year=y;}int get_year(){return year;}
};
int main()
{Cdrom acer; // ошибка: нет конструктора по умолчанию acer.set_speed(40);
acer.set_year(2004);//доступ к элементам структуры cout<<"\nCd-Rom Acer "<<acer.get_speed()<<acer.get_year(); return 0;

}
Исправить ситуацию можем путем создания конструктора по умолчанию, т.е. конструктора, у которого нет аргументов.
Cdrom(){speed=52;year=2008;cout<<"\nConstr-1";}
Пример 4. Добавлен конструктор по умолчанию
#include <iostream> using namespace std; class Cdrom{
int speed;//скорость int year;// год выпуска
public:
Cdrom(){speed=52;year=2008;cout<<"\nConstr-1";}
Cdrom(int s,int y=2004){speed=s;year=y;cout<<"\nConstr-2";} ~Cdrom(){cout<<"\nDestructor";}
void set_speed(int s){speed=s;} int get_speed(){return speed;} void set_year(int y){year=y;} int get_year(){return year;}
};
int main()
{Cdrom acer; Cdrom ne(48,2007); Cdrom me(52);
acer.set_speed(40); acer.set_year(2004);//доступ к элементам структуры
cout<<"\nCd-Rom Acer "<<acer.get_speed()<<acer.get_year(); return 0;
}
Конструктор по умолчанию можно создать также, используя значения по умолчанию, например, в классе имеется конструктор
Cdrom(int s=40,int y=2006){speed=s;year=y;}
Объекты создаются так:
Cdrom nn; Cdrom mm(42,2008);
Можно иметь только один конструктор по умолчанию.
Конструкторов может быть несколько, и они создаются с учѐтом правил перегрузки функций.
Каждый класс имеет неявно объявленные конструктор без параметров – конструктор по умолчанию, копирующий конструктор, копирующий оператор присваивания и деструктор.

Класс может иметь несколько конструкторов (с разными наборами параметров), но только один деструктор, причѐм у него нет параметров.
Деструктор
Деструктор только один и имеет такое же имя, как и класс, только перед именем ставим символ ―~‖. Деструктор не имеет аргументов.
Пример 5.
#include <iostream> using namespace std; class Cdrom{
int speed;//скорость int year;// год выпуска
public: Cdrom(){speed=32;year=2005;cout<<"\nConstr-1";} Cdrom(int s,int y=2006)
{speed=s;year=y;cout<<"\nConstr-2";} ~Cdrom(){cout<<"\nDestructor";} void set_speed(int s) {speed=s;} int get_speed() {return speed;} void set_year(int y){year=y;} int get_year(){return year;}
};
int main()
{Cdrom acer(40,2006);
Cdrom sony; //конструктор по умолчанию
Cdrom lg(52);
cout<<"\nCd-Rom Acer "<<acer.get_speed(); cout<<" god vypuska "<<acer.get_year(); cout<<"\nCd-Rom Sony "<<sony.get_speed(); cout<<" god vypuska "<<sony.get_year(); cout<<"\nCd-Rom LG "<<lg.get_speed(); cout<<" god vypuska "<<lg.get_year(); return 0;
}
Объекты
Из предыдущего примера
#include <iostream> using namespace std;
class Cdrom{// как в предыдущем примере: int speed;//скорость
int year;// год выпуска public:
Cdrom(){speed=32;year=2005;cout<<"\nConstr-1";}
Cdrom(int s,int y=2006){speed=s;year=y;cout<<"\nConstr-2";}

~Cdrom(){cout<<"\nDestructor";} void set_speed(int s) {speed=s;} int get_speed() {return speed;} void set_year(int y){year=y;} int get_year(){return year;}
};
int main()
{Cdrom acer(40,2006); // Объект acer Cdrom sony; // Объект sony
Cdrom lg(52); // Объект lg
cout<<"\nCd-Rom Acer "<<acer.get_speed(); cout<<" god vypuska "<<acer.get_year(); cout<<"\nCd-Rom Sony "<<sony.get_speed(); cout<<" god vypuska "<<sony.get_year(); cout<<"\nCd-Rom LG "<<lg.get_speed(); cout<<" god vypuska "<<lg.get_year(); return 0;
}
Динамическое выделение памяти объектам
Пример 6.
#include <iostream> using namespace std;
class Cdrom{// как в предыдущем примере: int speed;//скорость
int year;// год выпуска public:
Cdrom(){speed=32;year=2005;cout<<"\nConstr-1";}
Cdrom(int s,int y=2006){speed=s;year=y;cout<<"\nConstr-2";} ~Cdrom(){cout<<"\nDestructor";}
void set_speed(int s) {speed=s;} int get_speed() {return speed;} void set_year(int y){year=y;} int get_year(){return year;}
};
int main()
{Cdrom acer(40,2006); // Объект acer
Cdrom *pCd; pCd= new Cdrom(40,2004);
cout<<"\nCd-Rom "<<pCd->get_speed(); cout<<" god vypuska "<< pCd->get_year();
delete pCd;
return 0;
}
Оператор new вызывает конструкторы, а delete – деструкторы.
Пример 7. Массив объектов.
#include <iostream> using namespace std;
class Cdrom{// как в предыдущем примере int speed;//скорость
int year;// год выпуска public:
Cdrom(){speed=32;year=2005;cout<<"\nConstr-1";}

Cdrom(int s,int y=2006){speed=s;year=y;cout<<"\nConstr-2";} ~Cdrom(){cout<<"\nDestructor";}
void set_speed(int s) {speed=s;} int get_speed() {return speed;} void set_year(int y){year=y;} int get_year(){return year;}
};
int main()
{Cdrom acer(40,2006); // Объект acer
Cdrom ob[4];
for (int i=0;i<4;i++) {
ob[i].set_speed(40+i); cout<<ob[i].get_speed()<<”\n”;
}
return 0;
}
Пример 8. Инициализация массива объектов
#include <iostream> using namespace std; class samp {
int a; public:
samp(int n) { a = n; } int get_a() { return a; }
};
int main()
{ samp ob[4] = { -1, -2, -3, -4 };//Это сокращѐнная запись для // samp ob[4] = { samp(-1), samp(-2), samp(-3), samp(-4) };
int i;
for(i=0; i<4; i++) cout << ob[ i ].get_a() << ' '; return 0;
}
Пример 9. Инициализация массива объектов из примера 7
#include "stdafx.h" #include <iostream> using namespace std;
class Cdrom{
int speed;//скорость int year;// год выпуска
public: Cdrom(){speed=32;year=2005;cout<<"\nConstr-1";}
Cdrom(int s,int y=2006){speed=s;year=y;cout<<"\nConstr-2";} ~Cdrom(){cout<<"\nDestructor";}
void set_speed(int s) {speed=s;} int get_speed() {return speed;} void set_year(int y){year=y;} int get_year(){return year;}
};

int _tmain(int argc, _TCHAR* argv[])
{
Cdrom ob[4]={40,42,44,46}; for (int i=0;i<4;i++) {
cout<<ob[i].get_speed()<<"\n";
}
return 0;
}
Пример 10. Инициализация массива объектов с помощью конструктора с двумя параметрами.
#include "stdafx.h" #include <iostream> using namespace std;
class Cdrom{
int speed;//скорость int year;// год выпуска
public: Cdrom(){speed=32;year=2005;cout<<"\nConstr-1";}
Cdrom(int s,int y=2006){speed=s;year=y;cout<<"\nConstr-2";} ~Cdrom(){cout<<"\nDestructor";}
void set_speed(int s) {speed=s;} int get_speed() {return speed;} void set_year(int y){year=y;} int get_year(){return year;}
};
int _tmain(int argc, _TCHAR* argv[])
{
Cdrom ob[4]= {Cdrom(40,2006),Cdrom(42,2006),Cdrom(44,2007),Cdrom(46,2008)};
for (int i=0;i<4;i++) { cout<<ob[i].get_speed()<<"\n"; cout<<ob[i].get_year()<<"\n";
}
return 0;
}