<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://mit.spbau.ru/sewiki/index.php?action=history&amp;feed=atom&amp;title=%D0%9A%D0%BB%D0%B0%D1%81%D1%81%D1%8B</id>
		<title>Классы - История изменений</title>
		<link rel="self" type="application/atom+xml" href="http://mit.spbau.ru/sewiki/index.php?action=history&amp;feed=atom&amp;title=%D0%9A%D0%BB%D0%B0%D1%81%D1%81%D1%8B"/>
		<link rel="alternate" type="text/html" href="http://mit.spbau.ru/sewiki/index.php?title=%D0%9A%D0%BB%D0%B0%D1%81%D1%81%D1%8B&amp;action=history"/>
		<updated>2026-06-27T17:54:12Z</updated>
		<subtitle>История изменений этой страницы в вики</subtitle>
		<generator>MediaWiki 1.26.2</generator>

	<entry>
		<id>http://mit.spbau.ru/sewiki/index.php?title=%D0%9A%D0%BB%D0%B0%D1%81%D1%81%D1%8B&amp;diff=218&amp;oldid=prev</id>
		<title>Кристина Курьян: Новая страница: «'''Ликбез по лекции 8 октября'''   На прошлой лекции были рассмотрены следующие вопросы касаю…»</title>
		<link rel="alternate" type="text/html" href="http://mit.spbau.ru/sewiki/index.php?title=%D0%9A%D0%BB%D0%B0%D1%81%D1%81%D1%8B&amp;diff=218&amp;oldid=prev"/>
				<updated>2011-05-12T20:08:30Z</updated>
		
		<summary type="html">&lt;p&gt;Новая страница: «&amp;#039;&amp;#039;&amp;#039;Ликбез по лекции 8 октября&amp;#039;&amp;#039;&amp;#039;   На прошлой лекции были рассмотрены следующие вопросы касаю…»&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Новая страница&lt;/b&gt;&lt;/p&gt;&lt;div&gt;'''Ликбез по лекции 8 октября'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На прошлой лекции были рассмотрены следующие вопросы касающиеся классов: 	&lt;br /&gt;
* Методы &lt;br /&gt;
* Конструкторы&lt;br /&gt;
* Деструкторы&lt;br /&gt;
* Конструкторы копирования&lt;br /&gt;
* Оператор присваивания &lt;br /&gt;
&lt;br /&gt;
Поставим задачу: &lt;br /&gt;
&lt;br /&gt;
Необходимо написать класс рациональных чисел. Для начала напишем класс с 2 переменными m_num(числитель), m_denom(знаменатель): &lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct Rational &lt;br /&gt;
{ &lt;br /&gt;
	int m_num; &lt;br /&gt;
	int m_denom; &lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Добавим конструктор &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct Rational &lt;br /&gt;
{ &lt;br /&gt;
	int m_num; &lt;br /&gt;
	int m_denom; &lt;br /&gt;
	Rational(): m_num(0), m_denom(1)    // конструктор по умолчанию &lt;br /&gt;
	{} &lt;br /&gt;
&lt;br /&gt;
	Rational(int n): m_num(n), m_denom(1)  // конструктор для целых чисел&lt;br /&gt;
	{} &lt;br /&gt;
&lt;br /&gt;
	Rational(int a, int b): m_num(a), m_denom(b) // конструктор для дробей &lt;br /&gt;
	{} &lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Что бы избежать повторения, можно сделать 3 конструкторов 1 с параметрами по &lt;br /&gt;
умолчанию, таким образом получаем:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct Rational &lt;br /&gt;
{ &lt;br /&gt;
	int m_num; &lt;br /&gt;
	int m_denom; &lt;br /&gt;
	Rational(int a = 0, int b = 1): m_num(a), m_denom(b) &lt;br /&gt;
	{&lt;br /&gt;
		normalize();  // получим несократимую дробь.&lt;br /&gt;
	} &lt;br /&gt;
&lt;br /&gt;
	void normalize();  // метод для сокращения дробей &lt;br /&gt;
}; &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Но получившийся класс не является надежным. Рассмотрим его недостатки: &lt;br /&gt;
переменные m_num, m_denom являются открытыми, следовательно их можно &lt;br /&gt;
изменить из другого модуля и это изменения будет сложно отследить. Таким образом может произойти &lt;br /&gt;
нарушение инварианта у класса. Для решения этой проблемы необходимо установить идентификаторы доступа. &lt;br /&gt;
&lt;br /&gt;
В с++ существует 3 идентификатора. &lt;br /&gt;
* public — методы, переменные могут быть вызваны/изменены из кода другого модуля. &lt;br /&gt;
* private — методы, переменные могут вызывать только из модуля где они определены&lt;br /&gt;
* protected — будет рассказано позже. &lt;br /&gt;
&lt;br /&gt;
Пример: &lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct Rational &lt;br /&gt;
{ &lt;br /&gt;
private: &lt;br /&gt;
	int m_num; &lt;br /&gt;
	int m_denom; &lt;br /&gt;
public: &lt;br /&gt;
	Rational(int a = 0, int b = 1): m_num(a), m_denom(b)   // конструктор для дробей &lt;br /&gt;
	{} &lt;br /&gt;
}; &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь, из другого модуля переменные не могут быть изменены. Таким образом, вызовы типа &lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
Rational r(4, 5); &lt;br /&gt;
r.m_num = 10;  // будет ошибка &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
не позволят изменить переменные. &lt;br /&gt;
&lt;br /&gt;
Вопрос: &lt;br /&gt;
&lt;br /&gt;
Как корректно уметь получать, изменять и отслеживать изменения private &lt;br /&gt;
переменных. &lt;br /&gt;
&lt;br /&gt;
Ответ: &lt;br /&gt;
&lt;br /&gt;
Необходимо для каждой переменной завести пару методов get/set, которые будут &lt;br /&gt;
устанавливать и получать соответствующие значения. К примеру: &lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct Rational &lt;br /&gt;
{ &lt;br /&gt;
private: &lt;br /&gt;
	int m_num; &lt;br /&gt;
	int m_denom; &lt;br /&gt;
public: &lt;br /&gt;
	Rational(int a = 0, int b = 1): m_num(a), m_denom(b) &lt;br /&gt;
	{} &lt;br /&gt;
	&lt;br /&gt;
	void setNum(int a); &lt;br /&gt;
	int getNum(); &lt;br /&gt;
	void setDenom(int b); &lt;br /&gt;
	int getDenom(); &lt;br /&gt;
}; &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Замечание 1 &lt;br /&gt;
&lt;br /&gt;
Рассмотрим конструктор со списоком инициализации членов класса в данной задачи, то &lt;br /&gt;
есть: &lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
Rational(int a = 0, int b = 1): m_num(a), m_denom(b) // конструктор для дробей &lt;br /&gt;
{} &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Вопрос: &lt;br /&gt;
&lt;br /&gt;
Что будет если изменить порядок инициализации, то есть &lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
Rational(int a = 0, int b = 1): m_denom(b), m_num(a) &lt;br /&gt;
{} &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ответ: &lt;br /&gt;
&lt;br /&gt;
Ничего не измениться, так как переменные инициализируются в том порядке, в котором они описаны в классе, то есть &lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct Rational &lt;br /&gt;
{ &lt;br /&gt;
private: &lt;br /&gt;
	int m_num; &lt;br /&gt;
	int m_denom; &lt;br /&gt;
public: &lt;br /&gt;
	Rational(int a = 0, int b = 1): m_num(a), m_denom(b) &lt;br /&gt;
	{} &lt;br /&gt;
}; &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Всегда будет сначала будет инициализирована переменная m_num, а затем m_denom. &lt;br /&gt;
&lt;br /&gt;
Вопрос: &lt;br /&gt;
&lt;br /&gt;
В каком порядке будет происходить вызов деструкторов полей. &lt;br /&gt;
&lt;br /&gt;
Ответ: &lt;br /&gt;
&lt;br /&gt;
Вызов деструкторов происходит в порядке обратном вызову конструкторов. К примеру &lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct Rational &lt;br /&gt;
{ &lt;br /&gt;
private: &lt;br /&gt;
	int m_num; &lt;br /&gt;
	int m_denom; &lt;br /&gt;
public: &lt;br /&gt;
	Rational(int a = 0, int b = 1): m_num(a), m_denom(b)  // конструктор для дробей &lt;br /&gt;
	{} &lt;br /&gt;
}; &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Сначала будет вызван деструктор для m_denom, а затем для m_num. &lt;br /&gt;
Замечание 2(дополнение для оператора присваивания):&lt;br /&gt;
 &lt;br /&gt;
Может быть опасно присваивать объект самому себе, для запрета необходимо при перегрузке оператора присваивания делать сравнение с *this. &lt;br /&gt;
&lt;br /&gt;
Замечание 3 &lt;br /&gt;
&lt;br /&gt;
Для упрощения работы необходимо уметь легко отличать переменные класса от локальных объектов, создающихся во время работы класса. Существует множество &lt;br /&gt;
нотации, рассмотрим несколько примеров: &lt;br /&gt;
* int num_; // то есть после имени переменной класса необходимо ставит _ &lt;br /&gt;
* int _num; // то есть перед имени переменной класса необходимо ставит _, но если имя &lt;br /&gt;
вашей переменной начинается с большой буквы(к примеру _GHB), происходит конфликт &lt;br /&gt;
имен &lt;br /&gt;
* int myNum; &lt;br /&gt;
&lt;br /&gt;
Замечание 4 &lt;br /&gt;
&lt;br /&gt;
Идентификаторы доступа private, public не являются сигнатурой. &lt;br /&gt;
&lt;br /&gt;
Пример: &lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct Rational &lt;br /&gt;
{ &lt;br /&gt;
private: &lt;br /&gt;
	int m_num; &lt;br /&gt;
	int m_denom; &lt;br /&gt;
public: &lt;br /&gt;
	Rational(int a = 0, int b = 1); &lt;br /&gt;
	int getNum(); &lt;br /&gt;
}; &lt;br /&gt;
Rational::Rational(int a, int b) : m_num(a), m_denom(b) &lt;br /&gt;
{} &lt;br /&gt;
int Rational::getNum() &lt;br /&gt;
{ &lt;br /&gt;
return m_num; &lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Замечание 5 &lt;br /&gt;
&lt;br /&gt;
Если объявление функции находить в файле *,h, то функция по умолчанию становиться inline. &lt;br /&gt;
Рассмотрим пример &lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct Rational &lt;br /&gt;
{ &lt;br /&gt;
private: &lt;br /&gt;
	int m_num; &lt;br /&gt;
	int m_denom; &lt;br /&gt;
public: &lt;br /&gt;
	Rational(int a = 0, int b = 1): m_num(a), m_denom(b)  // конструктор для дробей &lt;br /&gt;
	{} &lt;br /&gt;
	&lt;br /&gt;
	int getNum() &lt;br /&gt;
	{ &lt;br /&gt;
		return m_num; &lt;br /&gt;
	} &lt;br /&gt;
}; &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
То есть теперь getNum() теперь является inline, то есть по стандарту, код может быть с оптимизирован компилятором, и в результате, метод getNum может автоматически быть встроеным в код. &lt;br /&gt;
&lt;br /&gt;
Замечание 6 &lt;br /&gt;
&lt;br /&gt;
ODR — one defenition rule &lt;br /&gt;
Это значит что не должно быть в программе двух inline функции с одинаковыми именам. &lt;br /&gt;
Так же для каждой inline функции должна быть известна её реализация.&lt;/div&gt;</summary>
		<author><name>Кристина Курьян</name></author>	</entry>

	</feed>