ООП Классы – 2
Ссылки Ссылка – еще одно имя объекта. Используйте ссылки вместо указателя. Это более безопасно. Complex c(10,10); Complex c2& = c; c2+=10; // изменяется c Complex c3&; // нельзя, имя есть, а самого объекта нет Complex c4* = &c2; // c4 указывает на с, т.к. &c2 == &c void swap(int a, int b) { // не работает, приходят копии объектов int tmp = a; a = b; b = tmp; } void swap(int& a, int& b) { // работает, приходят сами объекты int tmp = a; a = b; b = tmp; } Пример вызова: int a=10, b = 15; swap (a, b);
Ключевое слово this Указатель this доступен внутри метода объекта. Он указывает на сам объект, для которого вызван метод. Например: class Complex { private: float real, image; public: float getReal() { return this->real; // тоже самое, что и return real; } Пример использования: class Complex { private: float real, image; public: Complex& operator+=(const Complex& obj) { real += obj.real; image = obj.image; return *this; } void main() { Complex c1(1,1), c2(2,2), c3(3,3); c1+=c2+=c3; // c2 станет (5,5), а с1 станет (6,6) }
Проблема: некорректное неявное копирование объектов Класс для представления N-мерного вектора: class Vector { private: fload* coords; int size; public: Vector(int _size) { size = _size; coords = new float[size]; } float& operator[] (int pos) { return coords[pos]; } ~Vector() { delete[] coords; } … } Проблемный код: Vector a(3); a[0]=1; a[1]=1; a[2]=1; Vector b(3); b = a; // ссылка coords просто копируется b[0]=5; // у вектора а тоже поменяется a[0] test(a); // ссылка coords просто копируется Vector c = a; // ссылка coords просто копируется c[0] =5; // у вектора а тоже поменяется a[0] … void test(Vector test) { test[0] = 0; // у вектора а тоже поменяется a[0] … }
Конструктор копирования и оператор присваивания Везде, где происходит неявное конструктуироване нового объекта, посредством копирования старого, вызывается конструктор копирования класса. Он имеет вид: ClassName (const ClassName& copiedObj) { … } При присваивании одного объекта другому вызывается оператор присваивания. Он имеет вид: ClassName& operator=(const ClassName& copiedObj) { … } Например: class Vector { fload* coords; int size; Vector(const Vector& copiedObj) { // Конструктор копирования size = copiedObj.size; coords = new float[size]; for (int i=0; i
Решение: неявное копирование объектов Класс для представления N-мерного вектора: class Vector { private: fload* coords; int size; public: Vector(int _size) { size = _size; coords = new float[size]; } float& operator[] (int pos) { return coords[pos]; } ~Vector() { delete[] coords; } Vector(const Vector& copiedObj) { // Конструктор копирования size = copiedObj.size; coords = new float[size]; for (int i=0; i
Ссылки и неявное копирование Избегайте неявного копирования, посредством использования ссылок в аргументах функций. Например: class Complex{ private: float real, image; public: Complex operator+(Complex obj) { // аргумент приходит не по ссылке Complex sum(real+obj.real, image+obj.image); return sum; } Complex a(1,1), b(2,2); Complex c = a+b; // сначала b скопируется в obj, а потом попадет в operator+ функцию Корректнее: class Complex{ private: float real, image; public: Complex operator+(Complex& obj) { // аргумент приходит по ссылке Complex sum(real+obj.real, image+obj.image); return sum; } Complex a(1,1), b(2,2); Complex c = a+b; // b не копируется в obj, а передается напрямую по ссылке в operator+
Ключевое слово const Ключевое слово const означает, что состояние объекта менять нельзя. Это контролируется компилятором. Целесообразно использовать const для предотвращения возможных ошибок. Например: bool correctCompareArrays (const int a[], const int b[], int size) { for (int i=0; i
Ключевое слово const в определении метода объекта Ключевое слово const в определении метода объекта означает, что метод не меняет состояния объекта. Возможно существование 2-х версий одного метод (константный и обычный), тогда константный метод вызывается только для константных объектов, а обычный для неконстантных. Например: class Vector { private: fload* coords; int size; public: Vector(int _size) { size = _size; coords = new float[size]; } float operator[] (int pos) const { return coords[pos]; } float& operator[] (int pos) { return coords[pos]; } int size() const { // size = 0; - не скомпилируется return size; } void main() { Vector v(2); v[0] = 5; // вызовется float& operator[] (int pos) const Vector v2(2); v2[0] = 3; // не скомпилируется, т.к. вызывается float operator[] (int pos) const printf(Size: %d, v.size()); //работает }
Аргументы по умолчанию Проблема: дублирование кода class Date { private: int year, month, day; public: Date(int y, int m, int d) { year = y; month = m; day = d; } Date(int y, int m) { year = y; month = m; day = 1; } Date(int y) { year = y; month = 1; day = 1; } Date() { year = 1; month = 1; day = 1; } Решение: class Date { private: int year, month, day; public: Date(int y=1, int m=1, int d=1) { year = y; month = m; day = d; }