Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 27.02.2011, 22:50   #1
Janym
Пользователь
 
Регистрация: 27.02.2011
Сообщений: 22
По умолчанию Передача объекта в функцию, и его деструкторы

Такой вот код..

Код:
class MyBase1 {
public:
	 MyBase1()
	{
		cout << "Constr MyBase1 " << this << endl;
	}
	~MyBase1()
	{
		cout << "Destr MyBase1 " << this << endl; 
	}

};
class MyBase2 {
public:
	MyBase2()
	{
		cout << "Constre MyBase2 " << this <<  endl;
	}	
	~MyBase2()
	{
		cout << "Destr MyBase2 " << this << endl;
	}
};
class MyBase3 :  public MyBase1, MyBase2  {
public:
	MyBase3()
	{
		cout << "Constre base3 " << this <<  endl;
	}	
	~MyBase3()
	{
		cout << "Destr base3 " << this << endl;
	}
};


class MyDelClass : public MyBase3 {
public:
	MyDelClass()
	{
		cout << "Constr MyDelClass " << this << endl;
	}
	~MyDelClass()
	{
		cout << "Destr MyDelClass " << this << endl;
	}
};

void Funct(MyBase3 r)
{
	cout << "addr of r: " << &r <<  endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
	MyDelClass o;
	cout << "addr of o: " << &o << endl;
	Funct(o);
	
	return 0;
}
Заметил, что если в Funct() передавать по значению объект класса MyDelClass, при чём тип аргумента Funct сделать классом, от которого наследуется MeDelClass, т.е. MyBase3 то итог программы такой:

Constr MyBase1 0012FF57
Constre MyBase2 0012FF58
Constre base3 0012FF57
Constr MyDelClass 0012FF57
addr of o: 0012FF57
addr of r: 0012FE58
Destr base3 0012FE58
Destr MyBase2 0012FE59
Destr MyBase1 0012FE58
Destr base3 0012FE73
Destr MyBase2 0012FE74
Destr MyBase1 0012FE73
Destr MyDelClass 0012FF57
Destr base3 0012FF57
Destr MyBase2 0012FF58
Destr MyBase1 0012FF57

...Вызывается деструкторы объекта r, его адрес 0012FE58, 59, 58
Вызываются и у объекта o 0012FF57, 57, 58, 57
А между ними идёт вызов деструкторов 0012FE73, 74, 73. Откуда они берутся, это промежуточная переменная что ли??

Последний раз редактировалось Janym; 27.02.2011 в 23:04.
Janym вне форума Ответить с цитированием
Старый 27.02.2011, 23:38   #2
alex_x_x
Форумчанин
 
Регистрация: 31.01.2011
Сообщений: 160
По умолчанию

все просто, поменяйте void Funct(MyBase3 r) на void Funct(MyBase3& r) и они пропадут))
на самом деле в вашем случае для MyBase3 вызывается конструктор копирования, но так как он у вас явно не объявлен - вызывается по умолчанию
тем не менее деструкторы так же вызываются

вообщем это эффект создания временного объекта при передаче по значению
alex_x_x вне форума Ответить с цитированием
Старый 27.02.2011, 23:44   #3
profi
Участник клуба Подтвердите свой е-майл
 
Регистрация: 19.11.2007
Сообщений: 1,022
По умолчанию

Когда функция
Код:
void Funct(MyBase3 r)
{
	cout << "addr of r: " << &r <<  endl;
}
завершается вызываются деструкторы базовых классов и деструктор текущего класса для уничтожения объекта r.
Если конечно я правильно понял вопрос.

Последний раз редактировалось profi; 27.02.2011 в 23:55.
profi вне форума Ответить с цитированием
Старый 27.02.2011, 23:45   #4
onewho
Форумчанин
 
Регистрация: 29.09.2010
Сообщений: 636
По умолчанию

при передаче объекта в функцию по значению (а также при использовании объекта в кач-ве возвращаемого значения функции, а также при копирующей инициализации) создается временная копия объекта но конструктор не вызывается (логически это можно понять так - ведь конструктор нужен чтобы иницализировать объект с нуля объект, а нам нужно скопировать данные), но при выходе из области видимости - вызывается деструктор - в вашем случае объекта MyDelClass ( а он повлёк за собой деструкторы MyBase3, MyBase2 и MyBase1).
для таких случаев придумали копирующий конструктор, или как вариант передавать объект по ссылке.
onewho вне форума Ответить с цитированием
Старый 27.02.2011, 23:49   #5
profi
Участник клуба Подтвердите свой е-майл
 
Регистрация: 19.11.2007
Сообщений: 1,022
По умолчанию

onewho вчитался в ваши слова внимательнее и удалил сообщение .

Последний раз редактировалось profi; 27.02.2011 в 23:59.
profi вне форума Ответить с цитированием
Старый 27.02.2011, 23:54   #6
onewho
Форумчанин
 
Регистрация: 29.09.2010
Сообщений: 636
По умолчанию

спасибо, но разве я не написал то же самое ?
onewho вне форума Ответить с цитированием
Старый 28.02.2011, 00:16   #7
Janym
Пользователь
 
Регистрация: 27.02.2011
Сообщений: 22
По умолчанию

2 alex_x_x
Это понятно ) Лучше использовать * или по &. Просто стало интересно почему по значению такое получается.

2 onewho
Но в данном случае как раз переменная r и есть временная копия, зачем же ещё другую создавать с адресом 0012FE73 .. ?
Ведь при вызове кода:
Код:
MyBase3 o1
MyDelClass o2;
o1 = o2;
никаких лишних деструкторов не вызывается.
Janym вне форума Ответить с цитированием
Старый 28.02.2011, 00:25   #8
Obey-Kun
Линуксоид
Участник клуба
 
Аватар для Obey-Kun
 
Регистрация: 31.07.2009
Сообщений: 1,403
По умолчанию

Если у тебя есть функция void myFunc(MyClass x), то при её вызове myFunc(my_object) создастся копия объекта my_object (поэтому-то и вызывается конструктор! ведь надо создать копию), она-то и будет x. Так что если ты будешь менять x, то это не изменит my_object. Это называется передачей по значению.

Если у тебя есть функция void myFunc(MyClass &x), то при её вызове myFunc(my_object) создастся указатель на объект my_object, а при обращении к x этот указатель будет разыменовываться. Так что если ты будешь менять x, то это будет менять и my_object. Это называется передачей по ссылке.

Если ты хочешь запретить менять x, но не хочешь создавать копию объекта, используй void myFunc(const MyClass &x). Это называется передачей по константной ссылке.

Иногда используют также передачу по указателю void myFunc(MyClass *x) и по константному указателю void myFunc(const MyClass *x).
Я схожу с ума или это глючит реальность?
Jabber ID: obey@obey.su

Последний раз редактировалось Obey-Kun; 28.02.2011 в 12:41.
Obey-Kun вне форума Ответить с цитированием
Старый 28.02.2011, 00:39   #9
Janym
Пользователь
 
Регистрация: 27.02.2011
Сообщений: 22
По умолчанию

Цитата:
Если у тебя есть функция void myFunc(MyClass x), то при её вызове myFunc(my_object) создастся копия объекта my_object (поэтому-то и вызывается конструктор! ведь надо создать копию), она-то и будет x. Так что если ты будешь менять x, то это не изменит my_object. Это называется передачей по значению.

Копия не вызовет конструктор, а только деструктор.

Не понятно другое, зачем по мимо временной переменной r компилятор ещё где-то создаёт переменную..
Janym вне форума Ответить с цитированием
Старый 28.02.2011, 01:02   #10
onewho
Форумчанин
 
Регистрация: 29.09.2010
Сообщений: 636
По умолчанию

именно эта переменная r и создается! она же должна сразу инициализироваться с помощью копирующего конструктора.

Obey-Kun, не встречал такую запись void myFunc(class MyClass &x)
может ты имел ввиду void myFunc(const MyClass &x) ?
onewho вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Изменение свойств объекта не активируя его ndvikulov Microsoft Office Excel 16 16.09.2010 20:14
Передача метода объекта. the_deer_one Общие вопросы C/C++ 8 09.09.2010 15:07
Можно ли в макрос передать имя объекта, его вызывающего buagbu Microsoft Office Excel 3 16.04.2010 08:54
Передача объекта в функцию Юра_YUYU Общие вопросы C/C++ 14 18.01.2010 16:00
Проверка объекта после его уничтожения AHTuKiLLeR Общие вопросы Delphi 1 19.06.2009 10:43