views:

5921

answers:

3

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.

+8  A: 

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;
   }
dirkgently
But that's not a default ctor, Dirk (he said gently.)
Charlie Martin
Thank, it works now. Could someone explain why it works, though? I don't get how it calls the constructor of the parent class. i thought what i did (calling the parents constructor by itself would work)thanks
chustar
That's the syntax: the base class needs to be called from the initializer list. If you don't specify, the compiler thinks you wanted to call the base class's default constructor and hence the problem.
dirkgently
+3  A: 

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).

David Rodríguez - dribeas
+3  A: 

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.

Charlie Martin