Ошибка «Нет подходящего конструктора по умолчанию» в Visual C ++ - PullRequest
15 голосов
/ 02 апреля 2009

Я не понимаю. Я три часа смотрю на код и не вижу проблемы.

Класс, который я создаю и который называется TwoDayPackage, происходит от класса Package.

Вот как я определил конструктор:

    TwoDayPackage(string, string, string, string, int, string, string, string, string, int, float, float, float);

Вот как я реализую конструктор:

TwoDayPackage::TwoDayPackage(string sName, string sAddress, string sState, string sCountry, int sZIP, string rName, string rAddress, string rState, string rCountry, int rZIP, float weight, float cost, float flat)
{
Package::Package(sName, sAddress, sState, sCountry, sZIP, rName, rAddress, rState, rCountry, rZIP, weight, cost);
flatRate = flat;
}

Вот как я использую его в своей основной функции.

TwoDayPackage pack2(senderName, senderAddress, senderState, senderCountry, senderZIP, receipientName, receipientAddress, receipientState, receipientCountry, receipientZIP, weight, cost, flat);

Я знаю, что мой список аргументов довольно длинный, есть причина для этого. Спасибо.

Ответы [ 3 ]

23 голосов
/ 02 апреля 2009

следует использовать:

TwoDayPackage::TwoDayPackage(string sName, string sAddress, string sState, string  sCountry, int sZIP, string rName, string rAddress, string rState, string rCountry, int rZIP, float weight, float cost, float flat)
 :Package(sName, sAddress, sState, sCountry, sZIP, rName, rAddress, rState, rCountry, rZIP, weight, cost)
  {
    flatRate = flat;
   }
22 голосов
/ 02 апреля 2009

Ктор по умолчанию - это тот, который можно вызвать без аргументов. По крайней мере, с этим кодом у вас его нет: ctor по умолчанию также имеет подпись

ClassName::ClassName();

или каждый аргумент должен иметь значение по умолчанию.

Тем не менее, точка зрения Дирка о синтаксисе верна; если вы хотите вызвать родительские классы ctor, вы должны сделать это после этого двоеточия.


@ Ответ dirkgently показывает правильный синтаксис, но давайте немного его расширим. У вас есть два класса

public class Package {
    // ...
    Package( /* that horrible ctor arg list */){/*...*/}
    // ...
}

public class TwoDayPackage : public Package {
    // ...
    TwoDayPackage(/* another horrible ctor */);  // declaration only
    // ...
}

и тогда вы придете, чтобы определить его

TwoDayPackage::TwoDayPackage(string sName, string sAddress, 
                             string sState, string sCountry, 
                             int sZIP, string rName, 
                             string rAddress, string rState, 
                             string rCountry, int rZIP, 
                             float weight, float cost, float flat)
{

     Package::Package(sName, sAddress, sState, sCountry, sZIP, 
                      rName, rAddress, rState, rCountry, rZIP, 
                      weight, cost);
     flatRate = flat;
}

... но это не работает? Зачем? По сути, потому что то, что вы говорите в C ++, не имеет смысла: Package::Package просто называет ctor суперкласса и ничего с ним не делает. Вы можете создать новый объект класса Package, используя оператор new ,

     Package foo = new
         Package::Package(sName, sAddress, sState, sCountry, sZIP, 
                          rName, rAddress, rState, rCountry, rZIP, 
                          weight, cost);

но это все еще не то, что вы хотите сделать; то, что вы хотите , - это сказать С ++, чтобы он строил части пакета в TwoDayPackage, используя этот список аргументов. Вам не нужно иметь полное имя, потому что компилятор уже знает, что такое родительский класс.

Вы также можете просто присваивать значения в дочернем ctor, но это неэффективно, поскольку компилятор генерирует код для "нескольких поездок в скважину". Так что в C ++ есть специальный синтаксис, в котором инициализаторы ставятся после двоеточия, как показал Дирк.

Еще одна вещь: так как вы в любом случае просто присваиваете параметр плоскому, вы можете сказать

TwoDayPackage::TwoDayPackage(string sName, string sAddress, 
                             string sState, string sCountry, 
                             int sZIP, string rName, 
                             string rAddress, string rState, 
                             string rCountry, int rZIP, 
                             float weight, float cost, float flat) :
    Package(sName, sAddress, sState, sCountry, sZIP, 
            rName, rAddress, rState, rCountry, rZIP, weight, cost),
    flatRate(flat) 
{
}

Проверьте этот раздел C ++ FAQ Lite для получения дополнительной информации.

5 голосов
/ 02 апреля 2009

Ответ такой: dirkgently . Объяснение - последовательность инициализации в C ++.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...