HTML [44] |
Visual C++ и MFC [21] |
c++ [78] |
php [19] |
Javascript [15] |
C# [51] |
загрузки [0] |
XNA
[10]
создание игр с помощью xna
|
Главная » Статьи » c++ |
Ну что ж, приступим! Сконцетрируйтесь, закройте глаза. Подумайте о чем-то хорошем. Я надеюсь, Вы подумали о С++. Отдохнули? Продолжаем наше погружение в прекрасный мир совершенного языка. По крайней мере, некоторые так думают. По умолчанию, при инициализации одного объекта другим, С++ выполняет побитовое копирование (почленное копирование). Сильно сказано. Это означает, что один объект становится точной копией другого. Продемонстрируем всё вышесказанное на примере: #include<iostream.h> class A{ int a; public: void Set(int f){ a=f; } }; void main(){ A ist; ist.Set(4); A cpy=ist;//После выполнения этой строки cpy будет копией ist } Хотя в большинстве случаев в этом нет ничего страшного, существуют ситуации, когда побитовое копирование не должно использоваться. Например, когда объект выделяет память при своем создании: ПримерПусть у нас есть 2 обьекта G и J класса MyClass, выделяющего память при создании обьекта.Предположим, что обьект G уже существует. Это означает что обьект G уже выделил память. Далее предположим, что G использовался для инициализации обьекта J, как показано ниже: MyClass J=G; Если в данном случае используется побитовое копирование( почленное копирование). То J станет копией G. Это значит, что J будет использовать тот же участок выделенной памяти, что и G,вместо того, чтобы выделить свой. Это чрезвычайно плохо. Если например в классе MyClass есть деструктор, освобождающий память, то тогда одна и та же память будет очищена дважды при уничтожении G и J. #include<iostream.h> // Реализация описанного выше class MyClass{ public: int *x; MyClass(){ x=new int; } ~MyClass(){ delete x; } }; void main(){ // при создании обьекта G выделяется память в теле конструкторе MyClass G; // Вот-то и возникает проблема снова создаётся обьект, // а память в конструкторе не выделяется.В итоге указатель // J.x указывает в ту же область память ,что и G.x MyClass J=G; // при выходе из функции main 2 раза вызывается деструктор, // который очищает память отведённую при создании обьекта // то есть выполняется delete x для J и delete x для G // а так как J.x=G.x то отсюда следует вывод, что 2 раза // очищается одна и та же область памяти. Это повлечет за // собой ошибку на этапе выполнения программы } Проблема того же типа может возникнуть ещё в 2х случаях. Первый из них возникает, когда обьекта передается по значению в функцию в качестве аргумента: #include<iostream.h> class MyClass{ public: int *x; MyClass(){ x=new int; } ~MyClass(){ delete x; } }; void f(MyClass d){ } void main(){ // при создании обьекта G выделяется память в теле конструкторе MyClass G; // При передаче в функцию обьекта G по значению будет создана // дополнительная копия обьекта.Это будет проделано с помощью // побитового копирования (т.е. как обьяснялось выше память не будет // выделена) f(G); } Опять же возникнет ошибка на этапе выполнения программы !!! Второй появляется , когда временный обьект создается функцией возвращающей обьект в качестве своего значения. Пример : #include<iostream.h> class MyClass{ public: int *x; MyClass(){ x=new int; cout<<"It's me"; } ~MyClass(){ delete x; } }; MyClass f(){ MyClass s; // та же ошибка!!! При возврате значения создаётся побитовая копия // под которую не выделяется память return s; } void main(){ f(); }конструктор копирования Синтаксис конструктора копированияимя_класса(const имя_класса & W){ тело конструктора } Здесь W является ссылкой на обьект в правой части инициализации. Конструктор копирования может иметь также дополнительные параметры, если для них определены значения по умолчанию.Однако в любом случае первым параметром должна быть ссылка на объект выполняющий инициализацию. ПамяткаИнициализация возникает в 3х случаях.
Пример использования конструктора копирования.Эта программа создает простой класс «Безопасный массив». Поскольку место для массива выделено с помощью new, то для выделения памяти в случае, когда один обьект используется для инициализации другого,предоставляется конструктор копирования #include <iostream.h> #include <stdlib.h> // В классе array будет переменная указатель,переменная, отвечающая // за размер массива,конструктор копирования и 2 функции одна // для инициализации массива, другая для возврата i-го элемента class array{ int *p; int size;//размер массива public: array(int s){//конструктор p=new int[s];//выделение памяти под массив size=s;//Если все нормально то запоминаем размер массива } //конструктор копирования array(const array &d); //инициализация массива void Put(int i,int j){ if((i>=0)&&(i<size))// проверка на выход за границу массива p[i]=j; } //получение i-го элемента int Get(int i){ return p[i]; } }; // тело конструктора копированяи array::array(const array &f){ int i; p=new int[f.size];//выделение памяти if(!p) exit(1); for(i=0;i<f.size;i++) p[i]=f.p[i]; //заполнение элементами из переданного массива } void main(){ array n(10);//создание обьекта класса array int i; for(i=0;i<10;i++)n.Put(i,i);//Заполнение исходного массива for(i=9;i>=0;i--)cout<<n.Get(i);//Вывод на экран исходного массива cout<<endl; // создание нового обьекта и инициализация его уже существующим // в этой строке происходит вызов конструктора копирования в качестве параметра // ему передается n. array x=n; // Вывод на экран содержимого массива нового обьекта. for(i=0;i<10;i++)cout<<x.Get(i); } | |
Просмотров: 8659 | Рейтинг: 3.7/3 |
Всего комментариев: 0 | |