Консультация № 186442
13.07.2012, 12:03
0.00 руб.
0 13 1
Здравствуйте! У меня возникли сложности с таким вопросом:
Программирую под Windows в среде MS Visual Studio 2010 на C++.
1) Есть следующий код:
class CMyClass
{
public:
const std::wstring MyText;
CMyClass(const wchar_t* Text) : MyText(Text)
{
;
};

std::wstring Now() const throw()
{
return MyText;
};
};
Как получается так, что член класса m_wstrText объявлен не как указатель на экземпляр (например, MyClass* MyCl), а в виде ссылки на класс?
Я так понимаю, что экземпляр класса std::wstring создается внутри экземпляра класса Exception? Здесь нет "подводного камня"?
2) Как устроена функция Cout, в смысле, почему получается, что в нее можно вводить данные, к примеру, так:
std::cout << "MyText #" << (A+1) << std::endl;
В нее ведь сколько угодно так можно вводить, верно?
Большое спасибо за ответ!

Обсуждение

Неизвестный
13.07.2012, 12:35
общий
это ответ
Здравствуйте, Илья!

Начнем с конца :)
cout << x для C++ означает вызов функции operator <<(cout,x). А поскольку эта функция созвращает сам поток cout, то можно вызывать следующую функцию... Т.е. cout << x << y << z... - по сути, operator <<(operator <<(operator <<(cout,x),y),z)...

По первому вопросу - m_wstrText вообще нигде не объявлен! Если вы имеете в виду MyText - то это член-данные класса CMyClass, инициализируемый только в конструкторе (т.к. объявлен как const, его нельзя менять в других вызовах). Класс Exception у вас вообще нигде и никак не участвует (throw() у вас означает, что данный метод гарантиированно не генерирует никаких исключений. Кстати, рекомендую книгу Саттера "Решение сложных задач на C++", чтобы разобраться, чем эта спецификация плоха).

Извините, но ваш вопрос получился некорректно заданным... Если мой ответ недостаточен или непонятен - попробуйте сформулировать вопрос иначе, так как в вашем варианте на него просто нельзя однозначно корректно ответить :)

Неизвестный
13.07.2012, 13:13
общий
Большое спасибо за ответ! Вы все правильно поняли!
По первому вопросу - m_wstrText вообще нигде не объявлен! Если вы имеете в виду MyText - то это член-данные класса CMyClass, инициализируемый только в конструкторе (т.к. объявлен как const, его нельзя менять в других вызовах).

Да, извините... Я опечатался... Действительно имелось ввиду MyText.
Класс Exception у вас вообще нигде и никак не участвует (throw() у вас означает, что данный метод гарантиированно не генерирует никаких исключений.

Еще раз извините.Имелось ввиду не Exception, а CMyClass, снова опечатка. :)
На самом деле вопрос выглядит так:
1) Есть следующий код:
class CMyClass
{
public:
const std::wstring MyText;
CMyClass(const wchar_t* Text) : MyText(Text)
{
;
};

std::wstring Now() const throw()
{
return MyText;
};
};
Как получается так, что член класса MyText объявлен не как указатель на экземпляр (например, MyClass* MyCl), а в виде ссылки на класс?
Я так понимаю, что экземпляр класса std::wstring создается внутри экземпляра класса CMyClass? Здесь нет "подводного камня"?
2) Как устроена функция Cout, в смысле, почему получается, что в нее можно вводить данные, к примеру, так:
std::cout << "MyText #" << (A+1) << std::endl;
В нее ведь сколько угодно так можно вводить, верно?
Неизвестный
13.07.2012, 21:13
общий
cout - это не функция, а переменная, которая хранит объект потока вывода.
ostream cout;
Для класса ostream переопределен оператор <<. Можете рассматривать это как cout.print("MyText #).print(A+1).print("\n");
Оператор << не только выводит текст, но и возвращает значение - сам объект потока. Поэтому можно так интересно навешивать вызовы функций. "Вводить" можно сколько угодно: это все будет выглядеть как такая последовательность вызовов.
Неизвестный
13.07.2012, 21:24
общий
Большое спасибо за ответ!
А как же тогда получается так, что она выводит данные, преобразуя их в нужный формат?
Неизвестный
13.07.2012, 21:58
общий
Ну, Вас же не удивляет, что printf умеет выводить в нужном формате? :)

В C++ можно иметь много функций с одним именем, но разными типами параметров - например,
void a(), void a(int), void a(double) - это все разные функции. Поэтому operator <<(ostream,int) знает, как вывести целое число, <<(ostream,double) - как вывести число типа double. Есть и возможность более тонкой настройки...
Неизвестный
13.07.2012, 22:09
общий
Ну, Вас же не удивляет, что printf умеет выводить в нужном формате? :)

Когда-то удивляло. :)
В C++ можно иметь много функций с одним именем, но разными типами параметров - например, void a(), void a(int), void a(double) - это все разные функции. Поэтому operator <<(ostream,int) знает, как вывести целое число, <<(ostream,double) - как вывести число типа double.

Да, знаю, это называется перегрузкой. :)
Есть и возможность более тонкой настройки...

Кстати, а что Вы имели ввиду? :)
Неизвестный
13.07.2012, 22:13
общий
Кстати, а кто-нибудь может объяснить, как так получается, что объявление const std::wstring Stroka эквивалентно const basic_string <wchar_t> Stroka?
Неизвестный
13.07.2012, 23:49
общий
В заголовочном файле string есть такая строчка:
typedef basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t> > wstring;

Если компилятор встречает тип wstring (который здесь переназначен), то он соответственно заменяется.
Неизвестный
14.07.2012, 00:00
общий
Если компилятор встречает тип wstring (который здесь переназначен), то он соответственно заменяется.

Я также подумал, но вопрос вызывает то, что здесь написано: typedef basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t> > wstring;, а не просто: typedef basic_string<typename ReqType>. Именно это смутило...
Неизвестный
14.07.2012, 01:13
общий
В хелпе от 2003 тоже так стоит. А вот в хелпе от 2010 и в его библиотеке стоит как я написал. Возможно, сменили заголовок. Компилируется если по-старому написать? Я с++ уже давно не пользуюсь, тонкости не помню. Да и раньше это был С с классами, а не с СТЛ :)
Неизвестный
14.07.2012, 11:42
общий
Компилируется если по-старому написать?

Нет, не компилируется. :)
Об этом здесь написано: http://msdn.microsoft.com/en-us/library/wt3s3k55%28v=vs.80%29.aspx
Это и есть причина возникновения данного вопроса.
С этим разобрались. Теперь остался последний вопрос:
class CMyClass
{
public:
const std::wstring MyText;
CMyClass(const wchar_t* Text) : MyText(Text)
{
;
};

std::wstring Now() const throw()
{
return MyText;
};
};
Как получается, что строка const std::wstring MyText; компилируется успешно? Это же объявление объекта... Или оно воспринимается как ссылка на объект? Получается, что экземпляр этого класса - wstring - является членом класса CMyClass или это ссылка на него (wstring)?
Неизвестный
15.07.2012, 18:38
общий
std::wstring MyText - wtring является членом объекта. И хранится в нем целиком.
std::wstring *MyText; - wstring хранится где-о в другом месте (обычно в куче), а членом этого объекта является указатель на строку. Такое хранение гибче и дает возможность легко ссылаться на один объект из нескольких других.
А первый вариант обычно чуть быстрее (не всегда, раздутие хозяина может мешать) и требует меньше памяти. Но им удобно пользоваться только если внутренний объект должен использоваться исключительно одним хозяином и должен существовать всегда.
Это та же история, что и (int i) и (int *ptri), только здесь уже встраивается блок из нескольких переменных внутреннего класса.
Неизвестный
15.07.2012, 19:27
общий
Огромное спасибо за ответ!
Я многое уяснил! :)
Форма ответа