"Отсутствует подходящая ошибка конструктора по умолчанию" в 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. Объяснение - это последовательность инициализации в С++.
При построении класса сначала строятся все базовые классы. Если вы предоставляете вызов конструктору в списке инициализации, он вызывает соответствующий конструктор. Если базовый класс не отображается в списке инициализации, он будет сконфигурирован по умолчанию. Все это происходит до ввода блока конструктора (фигурные скобки).