Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 940
  • Last Modified:

Base class constructor calling

Ah hello.

If I have the following class definitions:

class Shape
{
public:
      Shape() { cout << "Constructing Shape object" << endl; }
      Shape(int n): name(n) { cout << "Constructing Shape object with parameter" << endl;}
      ~Shape() {cout << "Destroying Shape object " << endl; }
      int name;
};


class Rectangle : public Shape
{
public:
      Rectangle() { cout << "Constructing Rectangle object" << endl; }
      Rectangle(int n): name(n) { cout << "Constructing Rectangle object with parameter" << endl; } ***
      ~Rectangle() {cout << "Destroying Rectangle object " << endl; }
};



Now, I am getting a complier error regarding the line marked ***.

'error C2614: 'Rectangle' : illegal member initialization: 'name' is not a base or member'

Yet if I change the marked line to

Rectangle(int n) { name = n; cout << "Constructing Rectangle object with parameter" << endl; }

there is no complaint.

I am confused by this behaviour.  Linked to this question is a second:

Do I always have to *explicitly* call the base class constructor in circumstances like the above ?  Say I leave the constructor for Rectangle as this:

(1) Rectangle(int n) { name = n; cout << "Constructing Rectangle object with parameter" << endl; }

Now this is clearly initialising the inherited variable, name, right ?  Or should I be saying

(2) Rectangle(int n) : Shape(n) { cout << "Constructing Rectangle object with parameter" << endl; }

I have a gut feeling that the latter is probably considered better form, and would be the *only* option if 'name' was private in the Shape class, as Rectangle would not be able to access it via name = n.  But am I right ?  Is it a better idea to initialise inherited variables via the base class constructor call(2), or do so in the derived class constructor's body (1) and hence rely on the base class object to be constructed via its own default constructor ?

I know I have asked two questions here, but they are related, hence the points on offer are 20 for each question.

Thanks a lot !

0
mrwad99
Asked:
mrwad99
1 Solution
 
migoEXCommented:
The MSDN says:
"Only a member or base class can be in the initialization list for a class or structure."

You can think what happens if you had Shape defined as:
class Shape {
public:
Shape() : name(n) {...}
...
};

If the derived class would also try to initialize the "name" variable, the compiler would be confused - same variable can't be initialized twice.

I think the decision about which is better - (1) or (2) depends on the design, and I would say (2) or BOTH:

In case You're not sure the base class will initialize the name variable as I wand, you can write
Rectangle(int n) : Shape(n) {name = n; ...}
0
 
Mustak_ShaikhCommented:
mrwad99,

Answer to first question:
If you try to debug the above code(the correct one), you will observe
that compiler after encountering
Rectangle objRectangle(9);
will go to
Rectangle(int n)
compiler will not enter into this body,but from there it goes to Base class
and execute the base class constructor completly and come to the body of Rectangle constructor and execute it. that means at initializer list of Rectangle class, the base class object has not yet created and hence you can't refer any of its member.

2nd question: I guess the  last solution in this case is correct and a better solution. it make sense to force fully call the base class' s constructor.

Regards,
0
 
GaryFxCommented:
1.  You do not always have to call the base class constructor explicitly, but there are times when it's appropriate.

2.  Yes (almost), doing name = n inside the body of the Rectangle constructor is setting the value of the inherited member variable "name."   However, it is an assignment, not an initialization.  The initialization took place when the base class constructor was called, which happens before the body of the derived class constructor is executed.  

3.  I agree that in general it is better form to pass the parameter to the base class constructor.  However, since the intent of an int variable entitled "name" isn't at clear to me, it may not matter much in this case.  In many cases, it doesn't matter all that much.

Gary
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
_ys_Commented:
A general design principle is to make all member variables private by default. Occassionally they may be declared as protected. This would eliminate most of the questions you have asked.

Another best practice is to use an initialisation list, rather than to initialise (/assign) variables within the constructor body itself. For built-in [fundamental] types there would be no performance hit, but for a custom class initialisation and subsequent reassignment could be costly.
0
 
jcondeCommented:
This is what your function Rectangle(int) should look like:

Rectangle(int n)
: Shape(n)
{
  cout << "Constructing Rectangle object with parameter" << endl;
}
0
 
mrwad99Author Commented:
I am surprised at the feedback that this question generated !

Thanks to everyone for the advice; it seems that migoEX gave advice that completely answered the stated question and was clearly first to do so.  For that reason I have accepted his answer.

Overall cheers though to everyone who participated !
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Tackle projects and never again get stuck behind a technical roadblock.
Join Now