- •Void Print();
- •Void print()
- •Void main()
- •Void print()
- •Void main()
- •Void main()
- •Void print()
- •Void main()
- •Void print()
- •Void main()
- •Void main()
- •Void main()
- •Void main()
- •Void main()
- •Void main()
- •Void main()
- •Void main()
- •Void print();
- •Void Drob::print()
- •Void main()
- •Void main()
- •Void print();
- •Void Drob::print()
- •Void main()
- •Void main()
- •Void main()
- •Void main()
- •Void main()
- •Void main()
- •Void main()
- •Void main()
- •Void main()
- •Void main()
- •Void main()
- •Void main()
- •Void main ()
- •Void main ()
- •Void main ()
Void main()
{
MyClass a;
MyClass b=a;
}
В ДАННОМ примере происходит ошибка на этапе выполнения при вызове деструктора .
Так как при побитовом копировании из объекта a в объект b скопировался только адрес динамического массива . Следовательно оба объекта ссылаются на одну и туже динамическую память . При вызове деструктора b эта память удалится , а при вызове деструктора объекта а произойдет ошибка , так как в нем остался бит-указатель ссылающийся уже на удаленную память .
ПРИМЕР 2
Передача объекта в функцию в качестве параметров.
Void F(MyClass obj)
{
….
}
Void main()
{
MyClass a;
F(a);
}
Здесь при вызове функции Ф объекта а передается по значению , то есть будет производится копирование . Следовательно объект obj и объект а будут содержать адрес одной и той же динамической выделенной памяти .
При завершении работы функции Ф вызовется деструктор для obj и освободит динамическую память .
ПРИМЕР 3
Возврат объекта из функции в качестве возвращаемого значения.
MyClass F()
{
MyClass obj;
Return obj;
}
Void main()
{
F();
}
При возврате из функции в значение компилятор создает временный объект в который копируется возвращаемый объект .
В данном примере создастся временный объект , в который побитово скопируется obj .
При выходе из функции obj удаляется и вызывается деструктор . А во временном объекте остается указатель . При завершении работы функции мейн вызовется деструктор этого временного объекта , в котором произойдет ошибка при попытке освободить уже освобожденную память .
Для решения вышеописанных проблем используется конструктор копирования .
Синтаксис:
Имя_класса(имя_класса & obj)
Class MyClass
{
Int *p;
Public:
MyClass(const Myclass &obj)
{
P=new int[3];
For(int i=0;i<3;i++)
P[i]=obj.p[i];
}
};
Есть две формы вызова конструктора копирования!
1)MyClass a;
MyClas b=a;
2)MyClass c(a);
На самом деле конструктор копирования присутствует в классе всегда .
Если программист явно его не определяет , то компилятор его создает сам .
В этом случае копирование осуществляется побитово .
ПЕРЕГРУЗКА ОПЕРАЦИЙ ПРЕОБРАЗОВАНИЯ ТИПОВ
Синтаксис.
operator_тип_данных(для которого мы будем делать перегрузку)
{
тело
}
#include<iostream>
#include<stdio.h>
using namespace std;
class Drob
{
private:
int ch;
int zn;
public:
operator int()
{
return ch/zn;
}
operator double()
{
return (double)ch/zn;
}
};
Void main()
{
int n;
double d;
Drob obj(5,2);
n=(int)obj;
d=(double)obj;
n=obj;
d=obj;
}
Операторы преобразования типов можно перегружать только в виде методов класса.
Если необходимо обратное преобразование , то есть какой-то стандартный тип данных к нашему , то используется конструкторы с одним параметром того типа, который мы хотим преобразовать . Такие конструкторы называются конструкторами преобразования.
Int n=3;
Drob a;
A=(Drob)n; //a=Drob(n);
КЛЮЧЕВОЕ СЛОВО EXPLICIT
Пример 1 .
void f(Drob a)
{
a.print();
}