Обособяване на класове
Чете се информация за компютри, съдържаща:
име на модел | name | OmniBook XE |
цена | price | 5660 |
оценка | score | 76 |
OmniBook XE
5660
76
ACMA P300
1095
75
AMAX Poewrstation
1999
78
Търси се продукта с най-голямо отношение оценка/цена.
#include <iostream>
#include <string>
using namespace std;
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_score = next_score;
best_price = next_price;
}
}
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;
}
Интерфейс и капсулиране
#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;
/*скрити данни*/
double price;
/*скрити данни*/
int score;
/*скрити данни*/
};
int main()
{ Product best;
bool more = true;
while (more)
{ Product next;
next.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();
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;
}
void Product::print() const
{ cout << name
<< " Price: " << price
<< " Score: " << score << "\n"; }
* Неявен параметър на член-функция
set-функции - променят неявния си параметър
get-функции - не променят неявния си параметър, използване на const
Конструктори по подразбиране и
с параметри
* Конструкторът инициализира полетата (членовете) данни на обекта
* Предефиниране на функции
class Employee {
public:
Employee();
Employee(string emp_name,
double init_salary);
void set_salary(double new_salary);
string get_name() const;
double get_salary() const;
void print() const;
private:
string name;
double salary;
};
Employee::Employee(string emp_name, double
init_salary)
{ name = emp_name;
salary = init_salary; }
* Полета с данни - обекти от други класове
class Employee {
public:
Employee(string emp_name,
double init_salary,
int arrive_hour, int leave_hour);
...
private:
string name;
double salary;
Time arrive;
Time leave;
};
Employee(string emp_name, double init_salary,
int arrive_hour, int leave_hour)
{ name = emp_name;
salary = init_salary;
arrive = Time(arrive_hour, 0, 0);
leave = Time(leave_hour, 0, 0);
}
Достъп до полетата с данни
* Само членовете-функции имат достъп до скритите полета с данни
string get_name() const
{ return name; }
double get_salary() const { return salary; }
* Явни и неявни параметри на функции
-- член-функция с използване на достъпът до скритите
данни
void Employee::print() const
{ cout << "Name: " << name
<< " "
<<
"Salary: " << salary << "\n"; }
-- член-функция с използване на член-функции
от същия клас
void Employee::print() const
{ cout << "Name: " << get_name()
<< " "
<<
"Salary: " << get_salary() << "\n"; }
-- външна за класа функция
void print(Employee const &emp)
{ cout << "Name: " << emp.get_name()
<< " "
<<
"Salary: " << emp.get_salary() << "\n"; }
Принципи на обектно-ориентираното
програмиране
* Определяне на интерфейс
Игра, която обучава децата да познават часовника.
Clock |
draw |
set_time |
Time |
Time(hours, minutes) |
get_hours |
get_minutes |
is_same_as(Time) |
Player |
Player(name, initial_time) |
increment_score |
get_level |
Game |
play |
read_player_information |
play_round |
** Клас Clock:
class Clock {
public:
Clock();
Clock(Point c, double r);
void set_time(Time t);
void draw() const;
private:
Time current_time;
Point center;
double radius;
};
void Clock::set_time(Time t)
{ current_time = t; }
Рисуване на часовник:
- рисуване на кръг
- рисуване на часовите деления
- рисуване на минутните деления
- рисуване на часовата стрелка
- рисуване на минутната стрелка
Рисува часово или минутно деление:
void Clock::draw_tick(double angle, double
length) const
{ double alpha = PI/2 - 6*angle*PI/180;
Point from(center.get_x()
+ cos(alpha)*radius*(1-length),
center.get_y() + sin(alpha)*radius*(1-length));
Point to(center.get_x() +
cos(alpha)*radius,
center.get_y() + sin(alpha)*radius);
cwin << Line(from,
to);
}
Рисува стрелка:
void Clock::draw_hand(double angle, double
length) const
{ double alpha = PI/2 - 6*angle*PI/180;
Point from = center;
Point to(center.get_x() +
cos(alpha)*radius*length,
center.get_y() + sin(alpha)*radius*length);
cwin << Line(from,
to);
}
Рисува циферблат:
void Clock::draw() const
{ cwin << Circle(center, radius);
int i;
const double HOUR_TICK_LENGTH
= 0.2;
const double MINUTE_TICK_LENGTH
= 0.1;
const double HOUR_HAND_LENGTH
= 0.6;
const double MINUTE_HAND_LENGTH
= 0.75;
for (i = 0; i < 12; i++)
{ draw_tick(i * 5,
HOUR_TICK_LENGTH);
int j;
for (j
= 1; j <= 4; j++)
draw_tick(i * 5 + j, MINUTE_TICK_LENGTH);
}
draw_hand(current_time.get_minutes(),
MINUTE_HAND_LENGTH);
draw_hand((current_time.get_hours()
+
current_time.get_minutes()
/ 60.0) * 5, HOUR_HAND_LENGTH);
}
** Ще използваме готовия клас Time.
** Клас Player:
class Player {
public:
Player();
Player(string player_name,
int initial_level);
void increment_score();
int get_level() const;
string get_name() const;
private:
string name;
int score;
int level;
};
Player::Player(string player_name, int
initial_level)
{ name = player_name;
level = initial_level;
score = 0;
}
int Player::get_level() const
{ return level; }
string Player::get_name() const { return name; }
void Player::increment_score()
{ score++;
if (score % 5 == 0 and level
< 4) level++;
}
** Клас Game:
class Game {
public:
Game();
void play();
void read_player_information();
void play_round();
private:
Player player;
};
Game::Game() { rand_seed(); }
void Game::play()
{ read_player_information();
string response;
do
{ play_round();
response = cwin.get_string("Do
you want to play again? (y/n)");
} while (response == "y");
}
void Game::read_player_information()
{ string name = cwin.get_string("What
is your name?");
int initial_level;
do
{ initial_level =
cwin.get_int("At
what level do you want to start? (1-4)");
} while (initial_level <
1 or initial_level > 4);
player = Player(name, initial_level);
}
Изиграване на кръг:
- генериране на случайно време
- показване на времето
- получаване на отговор
- ако отговорът не е правилен, отново получаване на отговор
- ако отговорът е правилен - поздравления и увеличаване на точките
Генериране на случайно време:
Time Game::random_time()
{ int level = player.get_level();
int minutes;
if (level == 1) minutes =
0;
else if (level == 2) minutes
= 15 * rand_int(0, 3);
else if (level == 3) minutes
= 5 * rand_int(0, 11);
else minutes = rand_int(0,
59);
int hours = rand_int(1, 12);
return Time(hours, minutes,
0);
}
Получаване на отговор:
Time Game::get_guess()
{ int hours;
do
{ hours = cwin.get_int("Please
enter hours: (1-12)");
} while (hours < 1 or
hours > 12);
int minutes;
do
{ minutes = cwin.get_int("Please
enter minutes: (0-59)");
} while (minutes < 0 or
minutes > 59);
return Time(hours, minutes,
0);
}
Изиграване на кръг:
void Game::play_round()
{ cwin.clear();
Time t = random_time();
const double CLOCK_RADIUS
= 5;
Clock clock(Point(0, 0),
CLOCK_RADIUS);
clock.set_time(t);
clock.draw();
Time guess = get_guess();
if (t.seconds_from(guess)
!= 0) guess = get_guess();
string text;
if (t.seconds_from(guess)
== 0)
{ text = "Congratulations,
" + player.get_name()
+ "! That is correct.";
player.increment_score();
}
else
text =
"Sorry, " + player.get_name()
+ "! That is not correct.";
cwin << Message(Point(-CLOCK_RADIUS,
CLOCK_RADIUS + 1),text);
}
** Главна програма:
int main()
{ Game clock_game;
clock_game.play();
return 0;
}
** Цялата програма:
#include "ccc_win.cpp"
#include "ccc_time.cpp"
const double PI = 3.141592653589793;
class Clock {
public:
Clock();
Clock(Point c, double r);
void set_time(Time t);
void draw() const;
private:
void draw_tick(double angle,
double length) const;
void draw_hand(double angle,
double length) const;
Time current_time;
Point center;
double radius;
};
class Player {
public:
Player();
Player(string player_name,
int initial_level);
void increment_score();
int get_level() const;
string get_name() const;
private:
string name;
int score;
int level;
};
class Game {
public:
Game();
void play();
void read_player_information();
void play_round();
Time random_time();
Time get_guess();
private:
Player player;
};
void rand_seed()
/* PURPOSE: Set the seed of the random
number generator
*/
{ int seed = static_cast<int>(time(0));
srand(seed);
}
int rand_int(int a, int b)
/* PURPOSE: Return a random integer
in a range
RECEIVES: a - the bottom
of the range
b - the top of the range
RETURNS: A random number
x, a <= x and x <= b
*/
{ return a + rand() % (b - a + 1);
}
Clock::Clock(){}
Clock::Clock(Point c, double r)
/* RECEIVES: c - the center of the
clock
r - the radius of the clock
*/
{ center = c; radius
= r; }
void Clock::set_time(Time t)
/* PURPOSE: set the current time
RECEIVES: t - the time to
set
*/
{ current_time = t; }
void Clock::draw_tick(double angle, double
length) const
/* PURPOSE: draw a tick mark (hour
or minute mark)
RECEIVES: angle - the angle
in minutes (0...59, 0 = top)
length - the length of the tick mark
*/
{ double alpha = PI / 2 - 6 * angle
* PI / 180;
Point from(center.get_x()
+ cos(alpha) * radius * (1 - length),
center.get_y()
+ sin(alpha) * radius * (1 - length));
Point to(center.get_x() +
cos(alpha) * radius,
center.get_y()
+ sin(alpha) * radius);
cwin << Line(from,
to);
}
void Clock::draw_hand(double angle, double
length) const
/* PURPOSE: draw a hand, starting
from the center
RECEIVES: angle - the angle
in minutes (0...59, 0 = top)
length - the length of the hand
*/
{ double alpha = PI / 2 - 6 * angle
* PI / 180;
Point from = center;
Point to(center.get_x() +
cos(alpha) * radius * length,
center.get_y()
+ sin(alpha) * radius * length);
cwin << Line(from,
to);
}
void Clock::draw() const
/* PURPOSE: draw the clock, with
tick marks and hands
*/
{ cwin << Circle(center, radius);
int i;
const double HOUR_TICK_LENGTH
= 0.2;
const double MINUTE_TICK_LENGTH
= 0.1;
const double HOUR_HAND_LENGTH
= 0.6;
const double MINUTE_HAND_LENGTH
= 0.75;
for (i = 0; i < 12; i++)
{ draw_tick(i * 5,
HOUR_TICK_LENGTH);
int j;
for (j
= 1; j <= 4; j++)
draw_tick(i * 5 + j, MINUTE_TICK_LENGTH);
}
draw_hand(current_time.get_minutes(),
MINUTE_HAND_LENGTH);
draw_hand((current_time.get_hours()
+
current_time.get_minutes()
/ 60.0) * 5, HOUR_HAND_LENGTH);
}
Player::Player()
{ level = 1; score =
0; }
Player::Player(string player_name, int
initial_level)
/* RECEIVES: player_name - the player
name
initial_level - the player's level (1...4)
*/
{ name = player_name;
level = initial_level;
score = 0;
}
int Player::get_level() const
{ return level; }
string Player::get_name() const
{ return name; }
void Player::increment_score()
/* PURPOSE: increment score
REMARKS: moves to next
level if current level complete
*/
{ score++;
if (score % 5 == 0 and level
< 4) level++;
}
Game::Game(){ rand_seed(); }
void Game::play()
/* PURPOSE: plays the game while
the player wants to continue
*/
{ read_player_information();
string response;
do
{ play_round();
response
= cwin.get_string("Do you want to play again? (y/n)");
} while (response == "y");
}
void Game::read_player_information()
/* PURPOSE: reads player name and
level
*/
{ string name = cwin.get_string("What
is your name?");
int initial_level;
do
{ initial_level =
cwin.get_int("At what level do you want to start? (1-4)");
} while (initial_level <
1 or initial_level > 4);
player = Player(name, initial_level);
}
Time Game::random_time()
/* PURPOSE: make a random time,
depending on the level
RETURNS: the random
time
*/
{ int level = player.get_level();
int minutes;
if (level == 1) minutes =
0;
else if (level == 2) minutes
= 15 * rand_int(0, 3);
else if (level == 3) minutes
= 5 * rand_int(0, 11);
else minutes = rand_int(0,
59);
int hours = rand_int(1, 12);
return Time(hours, minutes,
0);
}
Time Game::get_guess()
/* PURPOSE: get a time input from
the user
RETURNS: the time guessed
by the user
*/
{ int hours;
do
{ hours = cwin.get_int("Please
enter hours: (1-12)");
} while (hours < 1 or
hours > 12);
int minutes;
do
{ minutes = cwin.get_int("Please
enter minutes: (0-59)");
} while (minutes < 0 or
minutes > 59);
return Time(hours, minutes,
0);
}
void Game::play_round()
/* PURPOSE: Play a round, with up
to two guesses
*/
{ cwin.clear();
Time t = random_time();
const double CLOCK_RADIUS
= 5;
Clock clock(Point(0, 0),
CLOCK_RADIUS);
clock.set_time(t);
clock.draw();
Time guess = get_guess();
if (t.seconds_from(guess)
!= 0)
guess =
get_guess();
string text;
if (t.seconds_from(guess)
== 0)
{ text = "Congratulations,
" + player.get_name()
+ "! That is correct.";
player.increment_score();
}
else
text =
"Sorry, " + player.get_name()
+ "! That is not correct.";
cwin << Message(Point(-CLOCK_RADIUS,
CLOCK_RADIUS + 1), text);
}
int main()
{ Game clock_game;
clock_game.play();
return 0;
}