Форум программистов, компьютерный форум CyberForum.ru

запуск конструкторов - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 13, средняя оценка - 4.77
2e1553ce
1 / 1 / 1
Регистрация: 16.12.2011
Сообщений: 47
30.01.2012, 11:16     запуск конструкторов #1
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class String                    
  {
  private:
    strCount* psc;              
  public:
    String()                    // конструктор 
      { psc = new strCount("NULL"); }
//---------------------------------------------------------
    String(char* s)             // конструктор
      { psc = new strCount(s); }
//---------------------------------------------------------
    String(String& S)           // конструктор
      {    
      psc = S.psc;
      (psc->count)++;
      }
 
  };
///////////////////////////////////////////////////////////
int main()
{
  String s3 = "Муха по полю пошла, муха денежку нашла";
  return 0;
}

Подскажите при создании объекта s3 будут включены все 3 конструктора ?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
30.01.2012, 11:16     запуск конструкторов
Посмотрите здесь:

C++ Перегрузка конструкторов
Наследование конструкторов? C++
C++ Наследование конструкторов
C++ Наследование конструкторов
Вызов конструкторов C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
30.01.2012, 11:23     запуск конструкторов #2
Код вообще не скомпилируется. Конструктор копии должен принимать константную ссылку.
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16828 / 5249 / 321
Регистрация: 30.03.2009
Сообщений: 14,132
Записей в блоге: 26
30.01.2012, 18:26     запуск конструкторов #3
Цитата Сообщение от 2e1553ce Посмотреть сообщение
Подскажите при создании объекта s3 будут включены все 3 конструктора ?
Воткни печать в каждый из конструкторов и подобные вопросы отпадут сами собой
NaV'i4ok
3 / 3 / 0
Регистрация: 18.03.2011
Сообщений: 85
30.01.2012, 19:04     запуск конструкторов #4
Цитата Сообщение от 2e1553ce Посмотреть сообщение
Подскажите при создании объекта s3 будут включены все 3 конструктора ?
будет вызван конструктор
Цитата Сообщение от 2e1553ce Посмотреть сообщение
String(char* s) // конструктор
{ psc = new strCount(s); }
LimitArE
а если точнее:то следующее аналогично:
Цитата Сообщение от 2e1553ce Посмотреть сообщение
String s3 = "Муха по полю пошла, муха денежку нашла";
C++
1
String s3=String("Муха по полю пошла, муха денежку нашла");
LosAngeles
Заблокирован
30.01.2012, 19:55     запуск конструкторов #5
Цитата Сообщение от silent_1991 Посмотреть сообщение
Конструктор копии должен принимать константную ссылку.
почему должен?
Teravisor
30 / 30 / 3
Регистрация: 07.08.2011
Сообщений: 89
30.01.2012, 20:00     запуск конструкторов #6
Цитата Сообщение от LosAngeles Посмотреть сообщение
почему должен?
По стандарту...
LosAngeles
Заблокирован
30.01.2012, 20:08     запуск конструкторов #7
A non-template constructor for class X is a copy constructor if its first parameter is of type X&, const X&,
volatile X& or const volatile X&, and either there are no other parameters or else all other parameters
have default arguments (8.3.6). [ Example: X::X(const X&) and X::X(X&,int=1) are copy constructors.
go
Эксперт C++
3582 / 1362 / 128
Регистрация: 16.04.2009
Сообщений: 4,528
30.01.2012, 20:21     запуск конструкторов #8
Например так
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
 
class obj 
{
private:
   std::string s;
public: 
   obj(const std::string _s = ""): s(_s) {};
   obj(const char s_[]): s (s_) {};
   std::string show() { return s; };  
};    
 
 
int main()
{
   obj a1, a2("abc"), a3 = "Hello world";
   std::cout << a1.show() << std::endl << a2.show() << std::endl << a3.show() << std::endl;
}
http://liveworkspace.org/code/03decd...346dfcfbecb4a6
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
31.01.2012, 03:27     запуск конструкторов #9
Цитата Сообщение от LosAngeles Посмотреть сообщение
почему должен?
В данном случае должен. Ибо здесь временный объект String, созданный при помощи конструктора String(char *) (кстати, ему бы тоже неплохо принимать const char *), передаётся в конструктор копии, а тот принимает неконстантную ссылку. Временный объект не может быть принять по константной ссылке. Поэтому на вопрос "Сколько конструкторов будет запущено в примере" ответ вполне однозначный: 0.
http://liveworkspace.org/code/76acef...2a852ae9e025ba
OstapBender
 Аватар для OstapBender
581 / 519 / 35
Регистрация: 22.03.2011
Сообщений: 1,585
31.01.2012, 04:15     запуск конструкторов #10
silent_1991, имхо ерунда.
это чисто требование gcc, чтобы КК принимал const& (неплохое требование).
http://liveworkspace.org/code/425cd2...b8cd268bffce03
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
31.01.2012, 04:49     запуск конструкторов #11
OstapBender, ничего подобного gcc не требует:
http://liveworkspace.org/code/b5df4a...40543243c2a435

Добавлено через 10 минут
Здесь конструктор копии вообще не замешан. Однако если func будет принимать константную ссылку, всё скомпилируется.
http://liveworkspace.org/code/76b0d6...7a554c1317bafb
2e1553ce
1 / 1 / 1
Регистрация: 16.12.2011
Сообщений: 47
31.01.2012, 08:48  [ТС]     запуск конструкторов #12
если комменты добавить , то запускается только второй (char* s) потом все уходит на обработку в класс StrCount.
Конструктор копии запускается при таком обявлении:
C++
1
String s2(s3);
Ну и первый соответственно при :
C++
1
String s4;
Разобрался
Chelioss
179 / 179 / 4
Регистрация: 08.01.2011
Сообщений: 1,131
31.01.2012, 09:34     запуск конструкторов #13
Цитата Сообщение от 2e1553ce Посмотреть сообщение
Подскажите при создании объекта s3 будут включены все 3 конструктора ?
Конструктор всегда один вызывается.
OstapBender
 Аватар для OstapBender
581 / 519 / 35
Регистрация: 22.03.2011
Сообщений: 1,585
31.01.2012, 12:37     запуск конструкторов #14
Цитата Сообщение от silent_1991 Посмотреть сообщение
здесь временный объект String, созданный при помощи конструктора String(char *) (кстати, ему бы тоже неплохо принимать const char *), передаётся в конструктор копии, а тот принимает неконстантную ссылку.
а это к чему??

Цитата Сообщение от Chelioss Посмотреть сообщение
Конструктор всегда один вызывается.
кстати только вчера видел пример вызова из 1го конструктора - другого
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
31.01.2012, 13:15     запуск конструкторов #15
Цитата Сообщение от OstapBender Посмотреть сообщение
а это к чему??
Запутался в кодах (перед глазами были разные вариант, в том числе такой String s(String("string")); )

Цитата Сообщение от OstapBender Посмотреть сообщение
пример вызова из 1го конструктора - другого
Вы о делегировании конструкторов из нового стандарта?
Chelioss
179 / 179 / 4
Регистрация: 08.01.2011
Сообщений: 1,131
31.01.2012, 19:20     запуск конструкторов #16
Цитата Сообщение от OstapBender Посмотреть сообщение
кстати только вчера видел пример вызова из 1го конструктора - другого
Я вообще-то не про это.
Сыроежка
Заблокирован
31.01.2012, 21:20     запуск конструкторов #17
Цитата Сообщение от 2e1553ce Посмотреть сообщение
если комменты добавить , то запускается только второй (char* s) потом все уходит на обработку в класс StrCount.
Конструктор копии запускается при таком обявлении:
C++
1
String s2(s3);
Ну и первый соответственно при :
C++
1
String s4;
Разобрался
Увы, вы преждевременно радуетесь, что вы разобрались. На самом деле у вас некорректные представления.
Итак, рассмотрим предложение создания вашего объекта

C++
1
  String s3 = "Муха по полю пошла, муха денежку нашла";
Ваш объект типа String не может инициализироваться символьным литералом. Поэтому в вашем классе ищется конструктор, который преобразует символьный литерал в объект класса String. Такому конструктору соответствует конструктор вида String(char* s). После того, как объект класса String для выражения инициализации, стоящего в правой части знака = создан, вызывается конструктор копирования String(String(char* s)). Итак, строка

C++
1
  String s3 = "Муха по полю пошла, муха денежку нашла";
соответствует вызову двух конструкторов, то есть эквивалетна предложению

C++
1
String s3( String( "Муха по полю пошла, муха денежку нашла" ) );
Вы сейчас будете мне возражать, что вы посмотрели с помощью режима отладки, и у вас на самом деле вызвался один конструктор String(char* s).вместо двух конструкторов String(String(char* s)), как я это утверждаю.

Дело в том, что для обспечения оптимизации стандарт С++ позволяет создавать временный объект в области памяти создаваемого объекта, а потому конструктор копирования разрешается опустить. То есть стандарт С++ разрешает, что когда запускается выражение String(char* s)., то не создается временный объект, который затем является операндом конструктора копирования, а создается объект сразу в памяти, выделенной объекту s3. Но чтобы вы убедились, что наличие и доступность конструктора копирования все равно требуются, проведите такой тест: сделайте конструктор копирования закрытым и попробуйте запустить вашу программу. То есть в вашем классе поставьте объявление конструктора копирования String(String& S) в секцию private вашего класса, и вы увидите, что к вашему удивлению программа не будет компилироваться, хотя конструктор, тот, один, String(char* s), который вы считали запускается, по-прежнему является открытым членом вашего класса. String .
Это означает, что в вашем примере должны запускаться два конструктора, но в целях обспецения оптимизации стандарт С++ разрешает опускать запуск конструктора копирования, так как, фактически, оба конструктора делают одну и ту же инициализациию создаваемого объекта, а потому излишне создание временного объекта, а затем с помощью него инициализировать ваш создаваемый объект. Но при этом конструктор копирования все равно должен быть доступен для вызова, иначе вы не сможете создать свой объект, так как формально должны вызываться два конструктора, как былло указано в начале.
2e1553ce
1 / 1 / 1
Регистрация: 16.12.2011
Сообщений: 47
01.02.2012, 08:58  [ТС]     запуск конструкторов #18
Цитата Сообщение от Сыроежка Посмотреть сообщение
Увы, вы преждевременно радуетесь, что вы разобрались. На самом деле у вас некорректные представления.
Итак, рассмотрим предложение создания вашего объекта

C++
1
  String s3 = "Муха по полю пошла, муха денежку нашла";
Ваш объект типа String не может инициализироваться символьным литералом. Поэтому в вашем классе ищется конструктор, который преобразует символьный литерал в объект класса String. Такому конструктору соответствует конструктор вида String(char* s). После того, как объект класса String для выражения инициализации, стоящего в правой части знака = создан, вызывается конструктор копирования String(String(char* s)). Итак, строка

C++
1
  String s3 = "Муха по полю пошла, муха денежку нашла";
соответствует вызову двух конструкторов, то есть эквивалетна предложению

C++
1
String s3( String( "Муха по полю пошла, муха денежку нашла" ) );
Вы сейчас будете мне возражать, что вы посмотрели с помощью режима отладки, и у вас на самом деле вызвался один конструктор String(char* s).вместо двух конструкторов String(String(char* s)), как я это утверждаю.

Дело в том, что для обспечения оптимизации стандарт С++ позволяет создавать временный объект в области памяти создаваемого объекта, а потому конструктор копирования разрешается опустить. То есть стандарт С++ разрешает, что когда запускается выражение String(char* s)., то не создается временный объект, который затем является операндом конструктора копирования, а создается объект сразу в памяти, выделенной объекту s3. Но чтобы вы убедились, что наличие и доступность конструктора копирования все равно требуются, проведите такой тест: сделайте конструктор копирования закрытым и попробуйте запустить вашу программу. То есть в вашем классе поставьте объявление конструктора копирования String(String& S) в секцию private вашего класса, и вы увидите, что к вашему удивлению программа не будет компилироваться, хотя конструктор, тот, один, String(char* s), который вы считали запускается, по-прежнему является открытым членом вашего класса. String .
Это означает, что в вашем примере должны запускаться два конструктора, но в целях обспецения оптимизации стандарт С++ разрешает опускать запуск конструктора копирования, так как, фактически, оба конструктора делают одну и ту же инициализациию создаваемого объекта, а потому излишне создание временного объекта, а затем с помощью него инициализировать ваш создаваемый объект. Но при этом конструктор копирования все равно должен быть доступен для вызова, иначе вы не сможете создать свой объект, так как формально должны вызываться два конструктора, как былло указано в начале.
Прикольно

Добавлено через 4 минуты
Только что попробовал в CodeGear Rad Studio C++ Builder , Поставил КОнструктор копии в приват секцию , нажал компилировать - ни 1 ошибки и варнинга:
C++
1
2
3
4
5
6
7
8
  private:
    strCount* psc;
    String(String& S)           // конструктор копирования
      {
        cout<<"String Konst Kopir"<<endl;
        psc = S.psc;
        (psc->count)++;
      }
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
01.02.2012, 09:04     запуск конструкторов #19
2e1553ce, билдер нельзя назвать строго соответствующим стандарту, и это ещё мягко сказано. Эталоном в данном случае является всё-таки g++, который действительно не компилирует изначальный код (и не скомпилирует приведённый выше, с закрытым конструктором копии), как я и говорил. Кстати, причину я назвал в сообщении 9 данной темы.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
01.02.2012, 13:31     запуск конструкторов
Еще ссылки по теме:

вызовы конструкторов C++
Наследование конструкторов C++
Наследование конструкторов C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Сыроежка
Заблокирован
01.02.2012, 13:31     запуск конструкторов #20
Цитата Сообщение от 2e1553ce Посмотреть сообщение
Прикольно

Добавлено через 4 минуты
Только что попробовал в CodeGear Rad Studio C++ Builder , Поставил КОнструктор копии в приват секцию , нажал компилировать - ни 1 ошибки и варнинга:
C++
1
2
3
4
5
6
7
8
  private:
    strCount* psc;
    String(String& S)           // конструктор копирования
      {
        cout<<"String Konst Kopir"<<endl;
        psc = S.psc;
        (psc->count)++;
      }
Поздравляю! Вы только что обнаружили баг компилятора CodeGear Rad Studio C++ Builder!
Есть два варинта. Либо этот компилятор при оптимизации игнорирует закрытость конструктора копирования и остается довольным, что тот просто определен в одной из секций класса, либо вообще даже не обращает внимание на существование конструктора копирования. В любом случае это - баг.
Я бы вас попросил еще один эксперимент проделать, а именно не определять конструктор копирования, а только его объявить в закрытой секции. То есть будет так

C++
1
2
3
  private:
    strCount* psc;
    String(String& S);           // конструктор копирования
Если и это скомпилируется, то баг компилятора очень серьезный!
Yandex
Объявления
01.02.2012, 13:31     запуск конструкторов
Ответ Создать тему
Опции темы

Текущее время: 11:45. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru