класс1_начало
.docТЕМА: Введение в классы.
Класс включает в себя данные и методы работы с этими данными.
Общий формат объявления класса имеет следующий вид:
class имя_класса { Закрытые данные и функции public: открытые данные и функции };
|
Класс может содержать как открытые, так и закрытые элементы .
По умолчанию все элементы класса являются закрытыми.
Ключевое слово public используется для объявления открытых элементов класса.
Конструктор – это функция, которая вызывается при создании объекта. Имя конструктора совпадает с именем класса. Конструктор может иметь параметры.
Деструктор – это функция, которая вызывается при разрушении объекта. Имя деструктора совпадает с именем конструктора, но предваряется символом “~”. Деструктор не может иметь параметров.
Пример.
class test{ private: int i; public: test(int _w=0){i=_w;cout<<"sozd ob i="<<i<<endl;} ~test(){cout<<"razrush ob i="<<i<<endl; } void print(){ cout<<" i="<<i<<endl;} };
main(){
test a(1); a.print(); test b; b.print();
. . . }
|
Примеры конструкторов:
test() {i=0;}//без параметра test(int _i) { i=_i;}//с параметром test(int _i=10){i=_i;}// с параметром по умолчанию
|
Любая функция-член имеет доступ к закрытым элементам класса. Конструктор test и функция print в классе test имеют доступ к переменной i.
Чтобы создать объект ”классового ” типа используется имя класса: например,
test a(1), b;
|
Альтернативные варианты инициализации объекта:
test a=1;//если конструктор принимает только один аргумент test a=test(1); test a(1);
|
После создания объект класса будет иметь собственную копию членов данных этого класса: в примере test a(1), b; каждый из объектов a и b будет иметь собственные копии переменной i.
Чтобы получить доступ к открытому члену класса через объект этого класса, используется оператор “точка”: например,
a.print(); b.print();
|
В объявлении класса содержатся, как правило, прототипы функций-членов.
Например, объявление класса test может быть следующим:.
class test{ private: int i; public: test(int _w=0); //к-р с параметром по умолчанию ~test(); //деструктор void print(); //функция без параметров и без возвращаемого значения };
|
Чтобы реализовать функцию, которая является членом класса, необходимо сообщить компилятору, какому классу она принадлежит, квалифицировать имя этой функции с именем класса:
test:: test(int _w=0) { i=_w; cout<<"sozd ob i="<<i<<endl; };
test:: ~test() {cout<<"razrush ob i="<<i<<endl; }
void test:: print() { cout<<" i="<<i<<endl;}
|
Оператор разрешения области видимости “::” квалифицирует имя члена вместе с именем его класса |
Встраиваемая функция – это небольшая (по объему кода) функция, код которой подставляется вместо ее вызова. |
Любая функция, которая определяется в объявлении класса, автоматически становится встраиваемой (если она не содержит циклы, переключатели, не является рекурсивной …).
Определение небольших функций-членов в объявлении класса – обычная практика в С++ программировании.
|
Указатель this
Каждый раз при создании в программе объекта-экземпляра класса строится специальный указатель, называемый this и содержащий адрес этого объекта. В следующей программе указатель this применяется при выводе значений переменных объекта. Если это выполняется без использования указателя this, компилятор сам, автоматически обеспечивает правильную адресацию переменных текущего объекта.
Указатель this выступает в роли неявно заданного указателя на текущий объект. Указатель this доступен только в функциях-членах класса и позволяет сослаться на объект, для которого вызвана функция. Чаще всего он находит применение в конструкторах, выполняющих резервирование памяти. Кроме того, в различных программах можно встретить операторы, возвращающие значение текущего значения при помощи указателя this:
return(*this);
Пример.
В классе primer используется конструктор и функция – показать данные (функция описана двумя способами show1 и show2). Добавьте в класс метод - конкатенация двух строк: конкатенация с this и без this.
#include <iostream>
using namespace std;
class primer{ char title[256];//по умолчанию эти переменные - приватные char autor[256]; public: primer(char*_title, char*_autor);//конструктор void show1();//показать с this void show2();//показать без this };
|
int main() { primer book("My life","Daria sergeeva"); book.show1(); book.show2(); return 0; }
|
primer::primer(char*_title, char*_autor) {strcpy(title,_title); strcpy(autor,_autor); }
void primer::show1() {cout<<this->title<<" "; cout<<this->autor<<endl; //далее круглые скобки необходимы, так как операция точка (.) имеет более //высокий приоритет cout<<(*this).title<<" "; cout<<(*this).autor<<endl; } void primer::show2() { cout<<title<<" "; cout<< autor<<endl; }
|
Результаты выполнения программы
My life Daria sergeeva My life Daria sergeeva My life Daria sergeeva
|
В С++ автоматически поддерживаются следующие функции-элементы:
– конструктор по умолчанию, если конструкторы не определены,
– конструктор копирования, если он не определен (выполняет поэлементное копирование нестатических элементов – поверхностное копирование),
– оператор присваивания, если он не определен,
– заданный по умолчанию деструктор, если он не определен,
Неявный конструктор копирования и неявный оператор присваивания вызывают проблемы в классах, использующих динамическую память.
Пример 3.
Класс комплексные числа.
Выполните программу.
#include <iostream>
using namespace std;
class cm{ float re,im; public: cm(){re=im=0;}//конструктор без параметров cm(int _re,int _im){re=_re;im=_im;}//конструктор с параметрами void set();//функция ввода(без параметров) void show();//функция печати (без параметров) cm sum(cm ob) ; //функция суммирования объекта ob и текущего объекта
int eq(cm ob);//функция сравнения двух объектов на равенство
cm sum1(int a);//функция прибавления к текущему объекту целого числа
} ;
|
int main() { cm ob1,ob2(5,-7),ob3;//создание 3-ех объектов ob2.show();//вывод объекта ob2 ob1.set(); ob1.show();//ввод и выод объекта ob1 ob3=ob1.sum(ob2); ob3.show();//нахождение объекта - суммы двух объектов //и вывод результата cout<<ob1.eq(ob2)<<endl;//вывод результата сравнения двух объектов ob1.sum1(8); ob1.show();//прибавление к компонентам объекта числа и //вывод результата return 0; }
|
void cm::set(void)//описание метода set {cout<<"re,im=? ";cin>>re>>im;}
void cm::show(void)// описание метода show {cout<<re; if(im>0)cout<<"+i"<<im<<endl; else cout<<"-i"<<-im<<endl;}
cm cm::sum(cm ob) //функция суммирования объекта ob и текущего объекта { cm t; t.re=re+ob.re; t.im=im+ob.im; return t;}
int cm::eq(cm ob)//функция сравнения двух объектов на равенство {return re==ob.re&&im==ob.im;}
cm cm::sum1(int a)//функция прибавления к текущему объекту целого числа {re=re+a; im=im+a; return *this; }
|
Результаты выполнения программы
5-i7 re,im=? 10 20 10+i20 15+i13 0 18+i28
|
Упражнение. Добавьте методы: вычитание, умножение, деление комплексных чисел, нахождение в текущем объекте суммы текущего объекта и объекта, заданного в качестве параметра, операция ++. Замените конструктор с параметрами конструктором с параметрами по умолчанию
|
Упражнение Объявите класс “Дробь” и напишите клиентскую программу
|
Массивы объектов можно создавать точно также, как создаются массивы значений других типов, например:
test ar[3];
Если класс включает параметризованный конструктор, то массив объектов такого класса можно инициализировать, например:
test ar[3]={-1,-2,-3};
При инициализации массива объектов, конструкторы которых принимают несколько аргументов, используется более длинный формат инициализации. Например,конструктор test1 принимает два аргумента:
class test1{
private:
int i,j;
public:
test1(int _i,int _j){i=_i; j=_j;}
};
main(){
//длинный формат инициализации массива объектов
test1 a[3]={ test1(1,2),test1(3,4),test1(5,6) };
. . .
}
Указатели на объекты позволяют также получить доступ к объекту.
Пример.
test a(1), *p; //объявляем объект a и указатель на него - p
a.print();
p=&a; //присваиваем указателю адрес объекта
p->print(); //получаем доступ к объекту с помощью указателя
Функции-“друзья” разрешают функциям, которые не являются членами этого класса, доступ к закрытым членам класса.
Для объявления функции “другом” класса в объявление класса включается прототип функции в public-разделе объявления класса, прототип предваряется ключевым словом friend.
Функции-“другу” в качестве параметров передается один или несколько объектов класса, для которого она является другом.
Реализация функции-друга не использует квалификацию имени функции именем класса.
Функция-“друг” вызывается обычным образом, т.е. без привязки к объекту ( и без использования оператора “точка”).
Пример. Функция-друг print используется для доступа к закрытой переменной класса.
class test{
private:
int i;
public:
test(int _w=0){i=_w;}
~test(){ }
friend void print(test ob);//функция print –“друг” класса test
};
//реализация функции print (print не является членом класса)
void print(test ob)
{
cout<<ob.i<<endl;//функция имеет право на прямой доступ к члену класса i
}
main(){
test a(1);
print(a);//функция-“друг” вызывается обычным образом
test b;
print(b);
. . .
}