C ++: компилятор жалуется на инициализацию переменных в конструкторе - PullRequest
1 голос
/ 24 июня 2010

В моем заголовке "Test.h" есть переменная класса, в которой нет конструктора без аргументов. И у меня есть конструктор, как это:

Test::Test() // <-- Here he complains:
             // error: no matching function for call to ‘Beer::Beer()’
{
   int i = 2;
   theVar = Beer(1, i); // Beer(int, int) is the only constructor
}

Но я инициализирую его после (пустого) списка инициализаторов в теле конструктора.

Как я могу решить это? Как называется эта проблема, если у нее есть имя?

Спасибо

Ответы [ 4 ]

14 голосов
/ 24 июня 2010

Вам необходимо использовать список инициализаторов.

Test::Test() : theVar(1, 2) {}

Если проблема в том, что i является результатом вызова некоторой другой функции, вы можете сделать что-то вроде

Test::Test() : theVar(1, compute_i()) {}

Проблема заключается в том, что тело конструктора выполняется после . Все члены инициализируются.

Они инициализируются первыми путем вызова тех конструкторов, которые указаны в списке инициализаторов, и если член не указан там, вызывая его конструктор по умолчанию.

Вот почему вы получаете сообщение об ошибке Beer::Beer(), так как ничего не указано, он пытается вызвать этот конструктор для инициализации theVar, и его не существует..

Затем после все члены инициализируются, выполняется тело конструктора (где вы выполняете присваивание , а не инициализацию theVar. Нокомпилятор никогда не заходит так далеко, потому что не может выполнить инициализацию.

3 голосов
/ 24 июня 2010

Вы должны использовать список инициализатора для каждой переменной-члена, которая имеет параметризованный конструктор:

Test::Test() :
   theVar( 1, 2 )
{
}

если вам нужно, чтобы параметры были вычисляемыми во время выполнения - используйте для этого статические функции-члены и вставьте вызовы к ним в список инициализатора.

1 голос
/ 24 июня 2010

Напишите так:

Test::Test() 
    : theVar(1, 2)
{ } 

в противном случае компилятор попытается инициализировать Beer конструктором по умолчанию, прежде чем он войдет в тело конструктора.Вы должны инициализировать переменные-члены перед вводом тела конструктора.

Вы также можете рассмотреть возможность использования конструктора по умолчанию и установить члены Beer внутри тела конструктора.

1 голос
/ 24 июня 2010

Вам необходимо указать c'or по умолчанию, потому что компилятор выполнит инициализацию по умолчанию для всех членов класса до , когда c'or запустится.Этого нельзя избежать.Однако вы можете использовать список инициализатора c'tor, чтобы указать пользовательский c'tor (я полагаю, вы это знаете).

Возможный обходной путь - добавить такой частный c'tor по умолчанию в Beer и сделайте Test другом Beer, чтобы другие не могли назвать его случайно.

Это, однако, недостаток дизайна.Лучший способ - изменить Base, чтобы он имел значимый c'or по умолчанию, или изменить Test, чтобы можно было инициализировать Base в списке инициализаторов c'tor.

...