План:
Използване на класове и обекти
Обособяване на класове
Капсулиране на данните
Член-функции
Конструктори по подразбиране и с параметри
Достъп до полетата с данни
Сравняване на член-функции с обикновени
функции
** Използване на класове и обекти (преговор)
В лекциите до тук за класовете са разгледани:
- конструиране на обект:
string name; // конструира
(създава, дефинира) низа name с
дължина 0
Employee harry("Hacher, Harry", 350); //
дефинира обекта harry
Time t(10, 10, 5); // дефинира момента
t като 10:10:05
- извеждане (получаване) на информация (данни) за обект:
cout <<
name.length(); //
дължината на низа name
cout << harry.get_name(); //
името на обекта harry
cout <<
t.hours(); //
часовете в (на) момента t
- модифициране (променяне на данните) на обект:
harry.set_salary(380); //
задава нова заплата 380 на обекта harry
t.add_seconds(20); //
добавя 20 секунди към времето на обекта t
Въведени са и основните понятия конструктор, член-функция и
операция точка.
|
OmniBook XE 5660 76 ACMA P300 1095 75 AMAX Poewrstation 1999 78 |
int main()
{
string best_name =
""; // име
double best_price = 0; //
цена
int best_score =
0; // оценка
bool more = true;
while (more)
{ string next_name; // име
double
next_price; // цена
int
next_score;
// оценка
cout
<< "Please enter the model name: ";
getline(cin, next_name);
cout
<< "Please enter the price: ";
cin
>> next_price;
cout
<< "Please enter the score: ";
cin
>> next_score;
string
remainder; /* read remainder of line */
getline(cin, remainder);
if
(next_price != 0)
{ if (best_price == 0 or
next_score/next_price
> best_score/best_price)
{
best_name = next_name;
best_price = next_price;
best_score =
next_score;
}
}
cout
<< "More data? (y/n) ";
string
answer;
getline(cin, answer);
if
(answer != "y") more = false;
}
cout << "The best
bang for the buck is " << best_name
<< " (Score: " << best_score
<< " Price: " << best_price
<< ")\n";
return 0;
}
nkirov@cpp % c++ bestval.cpp nkirov@cpp % ./a.out Please enter the model name: OmniBook XE 5660 76Please enter the price: Please enter the score: More data? (y/n) y Please enter the model name: ACMA P300 1095 75Please enter the price: Please enter the score: More data? (y/n) y Please enter the model name: AMAX Poewrstation 1999 78Please enter the price: Please enter the score: More data? (y/n) n The best value is ACMA P300 Price: 1095 Score: 75 |
Множествата от променливи за име (name), цена (price)
и оценка (score) описват един продукт и можем да
ги обединим в един клас (Product).
** Интерфейс и капсулиране, членове-функции.
Интерфейсът на класа се състои от всички членове-функции, които
ще обработват обектите от този клас.
За нашия пример:
class Product {
public:
Product(); // конструктор
void read(); // четене на данни за обекта
bool is_better_than(Product b) const; // сравняване на обекти
void print() const; // отпечетване на данните на обекта
private:
implementation details
};
** Второ програмно решение на задачата с използване на класове.
// product2.cpp
#include <iostream>
#include <string>
using namespace std;
/* ДЕФИНИЦИЯ НА КЛАСА
*/
class
Product {
public:
/* интерфейс, открита
част */
/* декларации на
член-функциите на класа */
Product(); /* създава нов продукт */
void
read(); /* чете
продукт */
bool
is_better_than(Product b) const;/* сравнява продукти */
void print()
const; /* отпечатва продукт */
private:
/* капсулиране, скрита част,
данни на класа */
string name; /* скрита данна name
*/
double price; /* скрита данна price
*/
int score; /* скрита данна score
*/
};
/* ИЗПОЛЗВАНЕ
НА КЛАСА */
int main()
{
Product best;
/* дефиниране на
обектa best от класа */
bool more = true;
while (more)
{ Product next; /* дефиниране на обектa next
от класа */
next.read();
/* извикване на
член-функция read на класа */
if
(next.is_better_than(best))
best = next;
cout
<< "More data? (y/n) ";
string answer;
getline(cin, answer);
if
(answer != "y") more = false;
}
cout << "The
best bang for the buck is ";
best.print(); /* извикване на член-функция print на класа */
return 0;
}
/* РЕАЛИЗАЦИЯ
НА КЛАСА */
/* дефиниция на
конструктор */
Product::Product()
{ price = 10000;
score
= 0;
}
/* дефиниция на
член-функция мутатор (set-функция) */
void
Product::read()
{ cout
<< "Please enter the model name: ";
getline(cin, name);
cout << "Please
enter the price: ";
cin >> price;
cout << "Please
enter the score: ";
cin >> score;
string remainder;
getline(cin,
remainder);
}
/* дефиниция на
член-функция за достъп (get-функция) */
bool
Product::is_better_than(Product b) const
{ if (price == 0) return false;
if (b.price == 0) return true;
if (score/price
> b.score/b.price) return true;
return false;
}
/* дефиниция на
член-функция за достъп (get-функция) */
void
Product::print() const
{ cout
<< name
<< " Price: " << price
<< " Score: " << score
<< "\n";
}
/* КРАЙ на
файла, съдържащ текста на програмата */
nkirov@cpp % c++ product2.cpp nkirov@cpp % ./a.out Please enter the model name: OmniBook XE 5660 76Please enter the price: Please enter the score: More data? (y/n) y Please enter the model name: ACMA P300 1095 75Please enter the price: Please enter the score: More data? (y/n) y Please enter the model name: AMAX Poewrstation 1999 78Please enter the price: Please enter the score: More data? (y/n) n The best value is ACMA P300 Price: 1095 Score: 75 |
Синтаксис на дефиниция на член-функция: тип на върнатата стойност, име на клас, ::, име на член-функция, параметри на функция.
Видове член-функции:
- set-функции (мутатори) - променят (стойността на) неявния си
параметър (данните на обекта):
декларация: void read();
извикване: next.read();
- get-функции (функции за достъп) - не променят (стойността на)
неявния си параметър (данните на обекта), обявяват се като
константни функции.
декларация: void print() const;
извикване: best.print();
class Time {Ако имаше пряк достъп до данните (не бяха капсулирани), то можеше да се получи невалидно време, например
public:
Time();
Time(int h, int m, int s);
void add_seconds(long s);
long seconds_from(Time t) const;
int get_seconds() const;
int get_minutes() const;
int get_hours() const;
private:
int hours; /* conjecture */
int minutes; /* conjecture */
int seconds; /* conjecture */
};
Time liftoff(19, 30, 0);Получава се 25:30:00!
/* liftoff is delayed by six hours */
/* won't compile, but suppose it did */
liftoff.hours = liftoff.hours + 6;
bool Product::is_better_than(Product b) const
{ if (b.price == 0) return false;
if (price == 0) return true;
return score / price > b.score / b.price;
}
Неявен формален параметър - текущия обект; явен формален параметър Product b.if (next.is_better_than(best)) ...
* Полета с данни - обекти от други класове.
Пример: Към класа Employee добавяме още данни - времето на пристигане на
работа и времето на тръгване от работа.
class Employee {
public:
Employee(string n,
double sal, int arr, int leav);
...
private:
string name;
double salary;
Time arrive;
Time leave;
};
Employee::Employee(string
n, double sal, int arr, int leav)
{ name = n;
salary = sal;
arrive = Time(arr, 0, 0);
leave = Time(leav, 0, 0);
}
Класът Employee
съдържа членове-данни arrive
и leave, които са обекти от клас
Time.
Начални стойности на
тези обекти се задават от конструкторите на съответните класове.
** Достъп до полетата с данни
* Само членовете-функции имат достъп до скритите полета с
данни (в секция private).
string Employee::get_name() const
{ return name;
}. // данна name
void
Employee::set_salary(double new_salary)
{ salary =
new_salary; //
данна
salary
}
Представянето на данните на класа (напр. клас Employee)
е скрито от потребителя на класа (напр. функция main).
Потребителят на класа знае само интерфейса на класа - публичните
член-функции с типовете на техните параметри и върнати стойности.
Пример: Класът Time,
написан от Кай Хорстман (3.
Низове и обекти).
class Time {
public:
Time();
Time(int h, int m, int s);
void add_seconds(long s);
long seconds_from(Time t) const;
int get_seconds() const;
int get_minutes() const;
int get_hours() const;
private:
long time_in_secs;
};
Реализациите (дефинициите) на
член-функциите също са скрити за потребителя на класа.
Пример: Дефиниции на член-функции на класа Time.
Time::Time(int hour, int min, int sec)
{
time_in_secs = 60 * 60 * hour + 60 * min + sec;
}
int Time::get_minutes() const
{
return (time_in_secs / 60) % 60;
}
int Time::seconds_from(Time t) const
{
return time_in_secs - t.time_in_secs;
}
** Сравняване на член-функции с
обикновени функции.
Примери: Отпечатване на името и
заплатата на служител (обект от клас Employee),
реализирано с три различни функции:
-- член-функция с използване на достъп до
скритите данни name и salary:
void
Employee::print() const
{ cout << "Name:
" << name << " "
<<
"Salary: " << salary << "\n";
}
-- член-функция с използване на член-функции
(за достъп) от същия клас get_name и get_salary:
void
Employee::print() const
{ cout << "Name:
" << get_name() << " "
<<
"Salary: " << get_salary() << "\n";
}
-- външна за класа функция с параметър
константен псевдоним от клас Employee:
void print(const Employee &emp)
{ cout << "Name:
" << emp.get_name() << " "
<<
"Salary: " << emp.get_salary() << "\n";
}
Пример: Разширена реализация на клас Employee с две реализации на функция raise_salary за увеличаване на заплатата на служител: член-функция на класа Employee и обикновена функция с параметър от тип Employee.
// employee.cppnkirov@cpp % c++ employee.cpp
ccc_time.cpp nkirov@cpp % ./a.out Name: Harry; Salary: 1100; Arrive: 8; Leave: 16 New salary 1210 Name: Harry Salary: 1210 nkirov@cpp % |
Явен (explicit) параметър | Неявен (implicit) параметър | |
параметър-променлива (не се променя) |
По подразбиране Пример: void print(Employee); print(harry); // параметър harry |
Използва се const Пример: void Employee::print() const; harry.print(); // параметър harry |
параметър-псевдоним (може да се промени) |
Използва
се & |
По
подразбиране |
** Разделяне програмата на:
-- заглавен файл (product.h),
-- дефиниции на функциите на класа (product.cpp),
-- използване на обекти от класа (prodtest.cpp).
Разделна компилация (за упражненията).