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

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

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

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 16.05.2010, 20:29   #1
atenon
Форумчанин
 
Регистрация: 05.12.2009
Сообщений: 253
По умолчанию Возвращение объекта из функции класса

Здравствуйте.
Возникла такая проблема. При возвращении объекта из метода класса, вместо того что бы его просто вывести на экран, как должно быть по коду(вернее как хотелось бы), начинается какаято фигня с вызовом перегружаемого конструктора.
Пожалуйста подскажите в чем ошибка!

Код:
#include "stdafx.h"
#include <iostream>
#include <time.h> 
#include <math.h> 
#include <iomanip> 
#include <ctype.h> 
#include <stdlib.h> 
#include <string.h> 
#include <assert.h> 
using namespace std;	
class String { 
	friend ostream &operator<< (ostream &, const String &); // Перегрузка операции вывода
public: 
	String(const char * = ""); // конструктор преобразования 
	String(const String &); // конструктор копии 
	~String(); // деструктор 
	String operator()(int, int); // возвращение подстроки 
	int getLength() const; // возвращение длины строки 
private: 
	char *sPtr; // указатель на начало строки 
	int length; // длина строки 
};
// Конструктор преобразования: преобразовывает char * в String 
String::String(const char *s) 
{
	cout << "Конструктор преобразования: " << s << endl; 
	length = strlen(s); // вычисление длины 
	sPtr = new char[length + 1]; // выделение памяти 
	strcpy(sPtr, s); // копирование строки аргумента в объект 
}
// Конструктор копии 
String::String(const String &copy) 
{ 
	cout << "Конструктор копии: " << copy.sPtr << endl; 
	length = copy.length; // копирование длины 
	sPtr = new char[length +1]; // выделение памяти 
	assert(sPtr != 0); // завершение, если память не выделена 
	strcpy(sPtr, copy.sPtr); // копирование строки 
}
// Деструктор 
String::~String() 
{ 
	cout << "Деструктор:"<< sPtr << endl; 
 
	delete [ ] sPtr; // освобождение памяти, отведенной строке 
}
	

String String::operator() (int index, int subLength) 
{ 
	cout<<"\n"<<"Вход в функцию"<<"\n";
	// подтверждение того, что индекс в диапазоне и длина подстроки >= 0 
	assert(index >= 0 && index < length && subLength >= 0); 
	 String sub; // пустой String 

	 // Определение длины подстроки 
	if ((subLength ==0) || (index + subLength > length)) // Если subLength== 0 то подстрока заканчивается на томже символе что и строка
		sub.length = length - index + 1; 
	else 
		sub.length = subLength + 1; 
	
	// удаление символа из объекта 
	delete sub.sPtr;
	// выделение памяти для подстроки 
	sub.sPtr = new char[sub.length]; 	

	// копирование подстроки в новый String 
	strncpy(sub.sPtr, &sPtr[index], sub.length); 
	sub.sPtr[sub.length] = '\0'; // завершение нового String 

	cout<<"Попытка вывести суб  "<<sub<<"\n";
return sub; // возвращение копии sub объекта String 
}
// Возвращение длины строки 
int String::getLength() const { return length;} 
	// Перегруженная операция вывода данных 
ostream &operator<< (ostream &output, const String &s)
{
	output << s.sPtr; 
	return output; // возможность сцепления 
}


int _tmain(int argc, _TCHAR* argv[])

{
	setlocale(LC_ALL, "Russian");
	String s1("поздравляем" ), s2( " с днем рождения" ), s3; 

	cout<<"---------------------------"<<"\n";
	// проверка перегруженной функции вызова операции ()// для подстроки 
	cout << "Подстрока si начиная с " << endl; 
	cout<< "О до 27, s1 (0, 27), равна: "; 
	cout<<s1(2, 5); cout << endl << endl; 
		cout<<"---------------------------"<<"\n";
	// проверка опции подстроки "до конца String" 
	cout << "Подстрока si начиная с" << endl 
	<< "28, si (28, 0), равна: " 
	<< s1(28, 0) << endl <<endl; // 0 означает до конца строки 
	
	return 0; 	 
}
Приходится бежать со всех ног, чтобы только остаться на том же месте! Если хочешь попасть в другое место, тогда нужно бежать по меньшей мере вдвое быстрее! Льюис Кэрол
atenon вне форума Ответить с цитированием
Старый 16.05.2010, 20:40   #2
BOBAH13
Android Developer
Старожил Подтвердите свой е-майл
 
Аватар для BOBAH13
 
Регистрация: 19.02.2007
Сообщений: 3,708
По умолчанию

Хм... может не в этом проблема, но объявлять сначала это
Код:
#include <string.h>
, а потом писать это
Код:
using namespace std;	
class String {
Ой как не красиво, и бог его знает что будет. Вообщем измените название вашего класса.
BOBAH13 вне форума Ответить с цитированием
Старый 16.05.2010, 20:46   #3
atenon
Форумчанин
 
Регистрация: 05.12.2009
Сообщений: 253
По умолчанию

Цитата:
Ой как не красиво, и бог его знает что будет. Вообщем измените название вашего класса.
У меня 11 методов в классе, все выдают то, что нужно. Но попробую всетаки изменить.
Нет не помогло.
Приходится бежать со всех ног, чтобы только остаться на том же месте! Если хочешь попасть в другое место, тогда нужно бежать по меньшей мере вдвое быстрее! Льюис Кэрол

Последний раз редактировалось atenon; 16.05.2010 в 20:52.
atenon вне форума Ответить с цитированием
Старый 17.05.2010, 00:21   #4
Carbon
JAVA BEAN
Участник клуба
 
Аватар для Carbon
 
Регистрация: 22.04.2007
Сообщений: 1,329
По умолчанию

Цитата:
Сообщение от BOBAH13 Посмотреть сообщение
Ой как не красиво, и бог его знает что будет. Вообщем измените название вашего класса.
Да, некрасиво, но работе совершенно не мешает.

Цитата:
начинается какаято фигня с вызовом перегружаемого конструктора
Какая фигня? Можно описание фигни, а то я по понедельникам плохой телепат.
Carbon вне форума Ответить с цитированием
Старый 17.05.2010, 06:01   #5
atenon
Форумчанин
 
Регистрация: 05.12.2009
Сообщений: 253
По умолчанию

Цитата:
Какая фигня? Можно описание фигни, а то я по понедельникам плохой телепат.
После выполнения строки
Код:
cout<<"Попытка вывести суб  "<<sub<<"\n";
Происходит вызов вот этого конструктора
Код:
// Конструктор копии 
String::String(const String &copy) 
{ 
	cout << "Конструктор копии: " << copy.sPtr << endl; 
	length = copy.length; // копирование длины 
	sPtr = new char[length +1]; // выделение памяти 
	assert(sPtr != 0); // завершение, если память не выделена 
	strcpy(sPtr, copy.sPtr); // копирование строки 
}
и сразу вызов деструктора.
После этого программа зависает.
Приходится бежать со всех ног, чтобы только остаться на том же месте! Если хочешь попасть в другое место, тогда нужно бежать по меньшей мере вдвое быстрее! Льюис Кэрол

Последний раз редактировалось atenon; 17.05.2010 в 19:45.
atenon вне форума Ответить с цитированием
Старый 17.05.2010, 08:34   #6
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
и сразу вызов деструктора.
Цитата:
assert is a macro that expands to an if statement; if test evaluates to zero, the assert macro calls the _assert function

void _RTLENTRY _EXPFUNC _assert(char * __cond, char * __file, int __line);

and aborts the program.
Вот видимо он и срабатывает у тебя
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 17.05.2010, 18:57   #7
atenon
Форумчанин
 
Регистрация: 05.12.2009
Сообщений: 253
По умолчанию

Мой английский хромает на все четыре ноги, поэтому я тупо удалил строку
Код:
	assert(index >= 0 && index < length && subLength >= 0);
Результата нет.. Не могу понять почему вызывается конструктор и деструктор???
Приходится бежать со всех ног, чтобы только остаться на том же месте! Если хочешь попасть в другое место, тогда нужно бежать по меньшей мере вдвое быстрее! Льюис Кэрол
atenon вне форума Ответить с цитированием
Старый 17.05.2010, 20:52   #8
netrino
Участник клуба
 
Аватар для netrino
 
Регистрация: 15.07.2008
Сообщений: 1,933
По умолчанию

Если срабатывает ассерт, то его не удалять надо, а смотреть где неправильные параметры переданы )
Код:
	// удаление символа из объекта 
	delete sub.sPtr; //  (1)
	// выделение памяти для подстроки 
	sub.sPtr = new char[sub.length]; // (2)

	// копирование подстроки в новый String 
	strncpy(sub.sPtr, &sPtr[index], sub.length); 
	sub.sPtr[sub.length] = '\0'; // (3)
В (1) нужно delete[]
В (2), в следствии (3), наверное нужно length+1.

Код:
	cout << "Подстрока si начиная с" << endl 
	<< "28, si (28, 0), равна: " 
	<< s1(28, 0) << endl <<endl; // 0 означает до конца строк
По-видимому это и есть причина срабатывания ассерта. Вы уверены, что в строке будет 28+ символов? )
netrino вне форума Ответить с цитированием
Старый 18.05.2010, 21:42   #9
atenon
Форумчанин
 
Регистрация: 05.12.2009
Сообщений: 253
По умолчанию

Работает!! (из-за такой мелочи столько просидел). Всем спасибо за помощь.

На счет вызова конструктора копии и деструктора, я так понимаю после выхода из области видимости функции срабатывает автоматически деструктор для очистки памяти, но перед этим создается копия, если ошибаюсь поправте?
Приходится бежать со всех ног, чтобы только остаться на том же месте! Если хочешь попасть в другое место, тогда нужно бежать по меньшей мере вдвое быстрее! Льюис Кэрол

Последний раз редактировалось atenon; 19.05.2010 в 06:19.
atenon вне форума Ответить с цитированием
Старый 19.05.2010, 03:24   #10
netrino
Участник клуба
 
Аватар для netrino
 
Регистрация: 15.07.2008
Сообщений: 1,933
По умолчанию

Цитата:
Код:
String String::operator() (int index, int subLength)
Возврат происходит по значению, поэтому перед выходом из ф-ции происходит копирование объекта в "результат ф-ции"(потому вызывается конструктор копии), затем происходит разрушение локального объекта sub(вызывается деструктор)
netrino вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Если в классе объявить объект другого класса,будет ли видно переменные первого класса из объекта второго? TwiX Общие вопросы Delphi 3 15.11.2009 00:54
Метод класса. Возвращение множества переменных. C# Arhe Помощь студентам 2 06.10.2009 18:11
Cоздание объекта класса из API одного сервиса. Ошибки =( ZeBriD Общие вопросы C/C++ 6 23.09.2009 11:10
Присваивание объекту родительского класса объекта дочернего Викдон Общие вопросы Delphi 0 07.02.2009 15:27