简体   繁体   中英

“No appropriate default constructor available” error in Visual C++

I don't get it. I've been staring at the code the code for three hours and I can't see the problem.

The class I'm creating, called TwoDayPackage is derived from a class called Package.

This is how I defined the constructor:

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

This is how I implement the constructor:

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

This is how i use it in my main function.

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

I know my argument list is pretty long, there's a reason for that. Thanks.

Should use:

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

A default ctor is one that can be called with no arguments. At least with this code, you don't have one: a default ctor either has the signature

ClassName::ClassName();

or every argument must have a default.

That said, Dirk's point about the syntax is correct; if you want to invoke the parent classes ctor, you should do it after that colon.


@dirkgently's answer shows the right syntax, but let's expand it a little bit. You've got two classes

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

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

and then you come along to define it

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

... but that doesn't work? Why? Basically, because what you're telling C++ doesn't make sense: the Package::Package is just naming the superclass's ctor and not doing anything with it. You could create a new object of class Package by using the new operator,

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

but that's still not what you want to do; what you want is to tell C++ to contruct the Package parts of TwoDayPackage using that arg list. You don't need to have the fully-qualified name, because the compiler already knows what the parent class is.

You could also just assign values in the child ctor, but that's inefficient, as it makes the compiler generate code for "multiple trips to the well". So C++ has a special syntax where initializers are put after a colon, as Dirk showed.

One more thing: since you're just assigning a parameter to flat anyway, you can say

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

Check this section of the C++ FAQ Lite for more.

The answer is that of dirkgently . The explanation is the initialization sequence in C++.

When constructing a class, all base classes are constructed first. If you provide a call to the constructor in the initialization list, then it will call the appropriate constructor. If the base class does not appear in the initialization list, then it will be default constructed. All this happens before entering the constructor block (curly braces).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM