"Отсутствует подходящая ошибка конструктора по умолчанию" в Visual С++

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

Создаваемый мной класс, называемый 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);

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

Ответы

Ответ 1

Должен использовать:

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;
   }

Ответ 2

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

ClassName::ClassName();

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

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


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

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;
}

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

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

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

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

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

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) 
{
}

Отметьте этот раздел в С++ FAQ Lite для более подробной информации.

Ответ 3

Ответ - dirkgently. Объяснение - это последовательность инициализации в С++.

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