Solved

Base class constructor calling

Posted on 2003-11-09
6
926 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
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Often, when implementing a feature, you won't know how certain events should be handled at the point where they occur and you'd rather defer to the user of your function or class. For example, a XML parser will extract a tag from the source code, wh…
What is C++ STL?: STL stands for Standard Template Library and is a part of standard C++ libraries. It contains many useful data structures (containers) and algorithms, which can spare you a lot of the time. Today we will look at the STL Vector. …
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

919 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

19 Experts available now in Live!

Get 1:1 Help Now