Solved

Base class constructor calling

Posted on 2003-11-09
6
925 Views
Last Modified: 2008-02-01
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
Comment
Question by:mrwad99
6 Comments
 
LVL 5

Accepted Solution

by:
migoEX earned 40 total points
ID: 9709917
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
 
LVL 1

Expert Comment

by:Mustak_Shaikh
ID: 9710820
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
 
LVL 6

Expert Comment

by:GaryFx
ID: 9711584
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
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 9

Expert Comment

by:_ys_
ID: 9714045
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
 
LVL 7

Expert Comment

by:jconde
ID: 9719644
This is what your function Rectangle(int) should look like:

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

Author Comment

by:mrwad99
ID: 9731154
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

What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Introduction This article is the first in a series of articles about the C/C++ Visual Studio Express debugger.  It provides a quick start guide in using the debugger. Part 2 focuses on additional topics in breakpoints.  Lastly, Part 3 focuses on th…
IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now