powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Двоеточие в констукторе
9 сообщений из 9, страница 1 из 1
Двоеточие в констукторе
    #38133534
MaximuS_G
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Всем привет. В одной из моих тем, не касающихся вопроса этого топика, я подымал вопрос о двоеточии в конструкторе.
Вот мой вопрос и ответ на него. К сожалению, ответ не прояснил для меня данную конструкцию. Буду благодарен, за более детальное объяснение.
Заранее спасибо!
список инициализацииMaximuS_GИ еще вопрос появился. Вот здесь я читаю про конструкторы, и автор приводит такой пример:
Рассмотрим простой класс:
Код: plaintext
1.
2.
3.
4.
5.
6.
class Message
{
private:
	unsigned Id_;
	std::string Text_;
};


При его создании компилятор автоматически создаст конструктор по умолчанию в котором будет вызван конструктор по умолчанию для каждого из членов, но только если член не является встроенным типом (int, double и т.д.) и деструктор:
Код: plaintext
1.
2.
3.
4.
Message()
	: Text_()
{
}


Я не могу понять как это так записано - Message() потом двоеточие, а потом Text_() . Подскажите, пожалуйста.
То что идет после имени конструктора после двоеточия - это список инициализации. В нем можно вызывать конструкторы членов класса.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
class Message
{
Message()
	: Text_("a")  // конструктор копирования
{
	Text_ = "b"; // оператор присваивания
}

private:
	unsigned Id_;
	std::string Text_;
};



Аналог без класса:
Код: plaintext
1.
2.
std::string Text_("a");
Text_ = "b";
...
Рейтинг: 0 / 0
Двоеточие в констукторе
    #38133594
Abstraction
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MaximuS_G,

Пусть у нас есть вот такая пара классов:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
class Base{
protected:
  std::string m_str;
public:
  Base(void){};
  Base(std::string s){m_str = s;};
};

class Derived : public Base{
private:
  std::pair<int,int> m_values;
public:
  Derived(void){std::cout << "This constructor does nothing." << std::endl;};
};

Как можно видеть, конструктор Derived выглядит очень просто. Но что он делает?
1) Вызывает конструктор базового класса Base;
1.1) Тот вызывает конструктор std::string для создания члена m_str.
2) Вызывает конструктор std::pair<int,int> для создания члена m_values.
3) И только потом вызывает operator<<(std::cout&, const char*) и далее по списку.

Все вызываемые конструкторы, в данном случае - конструкторы без параметров. Если такое поведение нас устраивает, то и хорошо. А если нет, то эти "предварительные" действия можно переопределить:
Код: plaintext
1.
2.
3.
4.
5.
//...
  Derived(std::string s, int v1, int v2)
    :  Base(s)
    :  m_values(v1, v2)
  {std::cout << "Body still does nothing, but the job made behind the scenes becomes more apparent." << std::endl;}
...
Рейтинг: 0 / 0
Двоеточие в констукторе
    #38133696
MaximuS_G
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Abstraction,
Спасибо большое за обширный пример. К сожалению, я еще не учил наследование, поэтому дополнительный незнакомый синтаксис усложняет понимание.
Насколько я понял, если класс А содержит поле, которое имеет тип класса B, то при описание конструктора для класса А, мы можем указать, какие параметры будут передаваться в конструктор класса B. Правильно?
Я вот пытаюсь простой пример сделать, но куча ошибок при компиляции вылетает:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
class B
{
public:
	int a;
	B(int a=0)
	{
		this->a = a;
	}
};

class A
{
	B ocObj;              //класс А содержит поле, которое имеет тип класса B
	A():                  //при описание конструктора для класса А
		B(int a)      //мы можем указать, какие параметры будут передаваться в конструктор класса B
	{};
};

int main()
{
	A obj;

}
...
Рейтинг: 0 / 0
Двоеточие в констукторе
    #38133754
Abstraction
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MaximuS_GAbstraction,
Спасибо большое за обширный пример. К сожалению, я еще не учил наследование, поэтому дополнительный незнакомый синтаксис усложняет понимание.
Насколько я понял, если класс А содержит поле, которое имеет тип класса B, то при описание конструктора для класса А, мы можем указать, какие параметры будут передаваться в конструктор класса B. Правильно?Нет "конструктора класса" в этом смысле, есть "конструктор экземпляра". Кроме того, с точки зрения пользователя класса есть только сигнатура конструктора - можно использовать лишь те аргументы, которые нам передали:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
class SomeData {
private:
  int m_a;
  float m_b;
public:
  explicit SomeData(int value = 0){ m_b = m_a = value; }
};

class MyClass{
private:
  SomeData m_member1;
  SomeData m_member2;
public:
  MyClass(int d1, int d2) : //SomeData(d1) - неправильно: как угадать, кого именно нужно так инициализировать?
  //SomeData(int d3) - неправильно тем более: у нас есть только d1 и d2, новых переменных вводить нельзя
  m_member1(d1), m_member2(d2) //Вот так правильно: сразу ясно, кого чем инициализировать
  { }
  
  //Обратите внимание: m_member2 в списке указан раньше... но это ни на что не повлияет, см. ниже
  explicit MyClass(int d) : m_member2(d), m_member1(d)
  { }

  //Можно вызывать любые допустимые соответствующими классами формы конструкторов:
  MyClass(void) : m_member1(), m_member2(-1)
  { }
};

Есть один нюанс: как и всегда в С++, перечисление действий через запятую означает, что выполниться они могут в другом порядке. В случае списков инициализации, конструкторы будут вызываться в том порядке, в котором соответствующие члены были объявлены в классе (т.е. сначала m_member1, потом m_member2 - для нашего примера), в каком бы порядке мы ни указывали их в списке инициализации.
...
Рейтинг: 0 / 0
Двоеточие в констукторе
    #38133771
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Abstraction как и всегда в С++, перечисление действий через запятую означает, что выполниться они могут в другом порядке
Не всегда.
В операторе следования запятые задают строгую последовательность вычисления.
Код: plaintext
1.
2.
3.
a = 0;
a = 1, b = a;
assert(b == 1); // гарантируется стандартом
...
Рейтинг: 0 / 0
Двоеточие в констукторе
    #38133820
MaximuS_G
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Abstraction,
Ага, спасибо большое, теперь намного понятнее. Получается все переменные, которые я получая в конструктор, я могу распределить между членами класса, правильно? А может одна переменная использоваться для инициализации нескольких объектов разных классов?
Переделал свой пример, теперь все работает:
class B
{
public:
int a;
B(int a=0)
{
this->a = a;
}
};

class A
{
B ocObj; //класс А содержит поле, которое имеет тип класса B
A(): //при описание конструктора для класса А
ocObj(a) //мы можем указать, какому экземпляру класса B передать в конструктор значение "a"
{};
};

int main()
{
A obj;
}
Спасибо большое за помощь! :)
...
Рейтинг: 0 / 0
Двоеточие в констукторе
    #38133837
Abstraction
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В операторе следования запятые задают строгую последовательность вычисления.*стучит себе по голове*
Да. Правильно. Вы же мне об этом и говорили.
"Как и в некоторых других местах C++,..."
авторА может одна переменная использоваться для инициализации нескольких объектов разных классов?Да, посмотрите ещё раз последний пример. Вообще, у Вас есть аргументы конструктора плюс любые иные переменные в области видимости (глобальные переменные, константы) плюс литералы/нумералы, и что угодно из этого Вы вправе передавать в качестве аргументов любых конструкторов в списке инициализации.
...
Рейтинг: 0 / 0
Двоеточие в констукторе
    #38133889
MaximuS_G
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AbstractionДа, посмотрите ещё раз последний пример. Вообще, у Вас есть аргументы конструктора плюс любые иные переменные в области видимости (глобальные переменные, константы) плюс литералы/нумералы, и что угодно из этого Вы вправе передавать в качестве аргументов любых конструкторов в списке инициализации.
Вас понял, все четко ясно. Спасибо большое!
Удачи! :)
...
Рейтинг: 0 / 0
Двоеточие в констукторе
    #38484838
alexfarm2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
/*Хочется тоже поучаствовать. Объяснено , конечно, замечательно, но, возможно, этот совсем простой код тоже кому-нибудь будет полезен, ведь последний пост Максимуса, говорит о том, что он не до конца разобрался. По моему вот то, что хотел Максимус, но так и не услышал*/

class B
{
int b;
public:
B(int x=0){b = x;} //А можно и так, но так никто не делает{this->b=x;}
int get_b(){return b;}
};

class A
{
B bb;
public: //здесь Максимус забыл, что конструктор всегда делается public:
A(int y):bb(y){};
int get_bb(){return bb.get_b();}
};
int main(){
A obj(5);
cout<<obj.get_bb();
}

//А в остальном у Максимуса все правильно
...
Рейтинг: 0 / 0
9 сообщений из 9, страница 1 из 1
Форумы / C++ [игнор отключен] [закрыт для гостей] / Двоеточие в констукторе
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]