Джесс Либерти - Освой самостоятельно С++ за 21 день.
return 0;
}
int * FuncOne()
{
int * pInt = new int (5):
cout << "the value of pint in FuncOne is: " << *pInt << endl:
return pInt;
}
7. Исправьте программу из упражнения 6.
#include <iostream.h>
int FuncOne();
int main()
{
int theInt = FuncOne();
cout << "the value of pint in main is: " << theInt << endl;
return 0:
}
int FuncOne()
{
int * pInt = new int (5);
cout << "the value of pint in FuncOne is: " << <<pInt << endl;
delete pint;
return temp;
}
8. Жучки: что неправильно в этой программе?
1: #include <iostream.h>
3: class CAT
4: {
5: public:
6: CAT(int age) { itsAge = age; }
7: ~CAT(){ }
8: int GetAge() const { return itsAge; }
9: private:
10: int itsAge:
11: };
12:
13: CAT & MakeCat(int age):
14: int main()
15: {
16: int age = 7;
17: CAT Boots = MakeCat(age);
18: cout << "Boots is " << Boots.GetAge() << " years oldn";
19: return 0:
20: }
22: CAT & MakeCat(int age)
23: {
24: CAT * pCat = new CAT(age);
25: return *pCat;
26: }
Функция MakeCat возвращает ссылку на объект класса CAT, созданный в свободной памяти. Но поскольку здесь не предусмотрена операция по освобождению этой памяти, создание нового объекта приводит к ее утечке.
9. Исправьте программу из упражнения 8.
1: #include <iostream.h>
2:
3: class CAT
4: {
5: public:
6: CAT(int age) { itsAge = age; }
7: ~CAT(){ }
8: int GetAgeO const { return itsAge;}
9: private:
10: int itsAge;
11: };
13: CAT * MakeCat(int age);
14: int main()
15: {
16: int age = 7;
17: CAT * Boots = MakeCat(age);
18: cout << "Boots is " << Boots.GetAge() << " years oldn";
19: delete Boots;
20: return 0;
21: }
23: CAT * MakeCat(int age)
24: {
25: return new CAT(age);
26: }
День 10
Контрольные вопросы
1. Если вы перегрузили функцию-член, как потом можно будет различить разные варианты функции?
Перегруженными называются функции-члены, которые имеют одно и то же имя, но отличаются по количеству или типу параметров.
2. Какая разница между определением и объявлением?
Определение резервирует память, а объявление — нет. Объявления часто являются и определениями, за исключением объявлений классов, прототипов функций и новых типов с помощью typedef.
3. Когда вызывается конструктор-копировщик?
Всегда, когда создается временная копия объекта. Это случается каждый раз, когда объект передается как значение.
4. Когда вызывается деструктор?
Деструктор вызывается при удалении объекта либо по причине выхода за пределы области видимости, либо при вызове оператора delete для указателя, указывающего на данный объект.
5. Чем отличается конструктор-копировщик от оператора присваивания (=)?
Оператор присваивания работает с существующим объектом, а конструктор-копировщик создает новый временный объект.
6. Что представляет собой указатель this?
Это скрытый параметр в каждой функции-члене, который указывает на сам объект.
7. Как различить перегрузку префиксных и постфиксных операторов приращения?
Префиксный оператор не принимает никаких параметров. Постфиксный оператор принимает один параметр типа int, который используется в качестве флага для компилятора, сообщающего о том, что это постфиксный оператор.
8. Можно ли перегрузить operator+ для переменных типа short int?
Нет, для встроенных типов нельзя перегружать никаких операторов.
9. Допускается ли в C++ перегрузка operator++ таким образом, чтобы он выполнял в классе операцию декремента?
Правомочно, но этого делать не стоит. Операторы следует перегружать таким способом, который должен быть понятен любому читателю вашей программы.
10. Как устанавливается тип возврата в объявлениях функций операторов преобразования типов?
Никак. Подобно конструкторам и деструкторам, они не имеют никаких возвращаемых значений.
Упражнения
1. Представьте объявление класса SimpleCircle (простая окружность) с единственной переменой-членом itsRadius (радиус). В классе должны использоваться конструктор и деструктор, заданные по умолчанию, а также метод установки радиуса.
class SimpleCircle
{
public:
SimpleCircle();
~SimpleCircle();
void SetRadius(int);
int GetRadiusO;
private:
int itsRadius;
};
2. Используя класс, созданный в упражнении !, с помошью конструктора, заданного по умолчанию, инициализируйте переменную itsRadius значением 5.
SimpleCircle::SimpleCircle():
itsRadius(5);
{ }
3. Добавьте в класс новый конструктор, который присваивает значение своего пара-
метра переменной itsRadius.
SimpleCircle::SimpleCircle(int radius):
itsRadius(radius)
{ }
4. Перегрузите операторы преинкремента и постинкремента для использования в ва-
шем классе SimpleCircle с переменной itsRadius.
const SimpleCircle& SimpleCircle::operator++()
{
++(itsRadius);
return *this;
}
// постфиксный оператор Operator ++(int).
// Выборка, затем инкрементирование
const SimpleCircle SimpleCircle::operator++ (int)
// обьявляем локальный обьект класса SimpleCircle и инициализируем его значением
* this
SimpleCircle temp(*this);
++(itsRadius);
return temp;
}
5. Измените SimpleCircle таким образом, чтобы сохранять itsRadius в динамической области памяти и фиксировать существующие методы.
class SimpleCircle
{
public:
SimpleCircle();
SimpleCircle(int);
~SimpleCircle();
void SetRadius(int);
int GetRadius();
const SimpleCircle& operator++();
const SimpleCircle operator++(int);
private:
int *itsRadius;
};
SimpleCircle::SimpleCircle()
{itsRadius = new int(5);}
SimpleCircle::SimpleCircle(int radius)
{itsRadius = new int(radius);}
SimpleCircle::~SimpleCircle()
{
delete itsRadius;
}
const SimpleCircle& SimpleCircle::operator++()
{
++(*itsRadius);
return <<this;
}
// Постфиксный оператор Operator++(int).
// Выборка, затем инкрементирование
const SimpleCircle SimpleCircle::operator++ (int)
{
// объявляем локальный объект класса SimpleCircle и инициализируем его значением
*this
SimpleCircle temp(<<this);
++(*itsRadius);
return temp;
}
6. Создайте в классе SimpleCircle конструктор-копировщик.
SimpleCircle::SimpleCircle(const SimpleCircle & rhs)
{
int val = rhs.GetRadius();
itsRadius = new int(val);
}
7. Перегрузите в классе SimpleCircle оператор присваивания.
SimpleCircle& SimpleCircle::operator=(const SimpleCircle & rhs)
{
if (this == &rhs)
return *tnis;
delete itsRadius;
itsRadius = new int;
*itsRadius = rhs.GetRadius();
return *this;
}
8. Напишите программу, которая создает два объекта класса SimpleCircle. Для создания одного объекта используйте конструктор, заданный по умолчанию, а второму экземпляру при объявлении присвойте значение 9. С каждым из объектов используйте оператор инкремента и выведите полученные значения на печать. Наконец, присвойте значение одного объекта другому объекту и выведите результат на печать.
#include <iostream.h>
class SimpleCircle
{
public:
// конструкторы
SimpleCircle();
SimpleCircle(int);
SimpleCircle(const SimpleCircle &);
~SimpleCircle() {}
// методы доступа к данным
void SetRadius(int);
int GetRadius() const;
// операторы
const SimpleCircle& operator++();
const SimpleCircle operator++(int);
SimpleCircle& operator=(const SimpleCircle &):
private:
int *itsRadius;
};
SimpleCircle::SimpleCircle()
{itsRadius = new int(5);}
SimpleCircle::SimpleCircle(int radius)
{itsRadius = new int(radius);}
SimpleCircle::SimpleCircle(const SimpleCircle & rh$)
{
int val = rhs.GetRadius();
itsRadius = new int(val);
}
SimpleCircle::~SimpleCircle()
{
delete itsRadius;
}
SimpleCircleS SimpleCircle :operator=(const SimpleCircle & rhs)
{
if (this == &rhs)
return <<this;
*itsRadius = rhs.GetRadius();
return *this;
}
const SimpleCircle& SimpleCircle::operator++()
{
++(*itsRadius);
return *this;
}
// Постфиксный оператор Operator ++(int).
// Выборка, затем инкрементирование
const SimpleCircle SimpleCircle::operator++ (int)
{
// объявляем локальный объект класса SimpleCircle и инициализируем его значением
*this
SimpleCircle ternp(*this);
++(*itsRadius);
return temp;
}
int SimpleCircle::GetRadius() const
{
return ~itsRadius;
}
int main()
{
SimpleCircle CircleOne, CircleTwo(9);
CircleOne++;
++CircleTwo;
cout << "CircleOne: " << CircleOne.GetRadius() << endl;
cout << "CircleTwo: " << CircleTwo.GetRadius() << endl;
CircleOne = CircleTwo;
cout << "CircleOne: " << CircleOne.GetRadius() << endl:
cout << "CircleTwo: " << CircleTwo.GetRadius() << endl;
return 0;
}
9. Жучки: что неправильно в следующем примере использования оператора присваивания?