default parameters and inheritance

  • Thread starter Ernst Murnleitner
  • Start date
E

Ernst Murnleitner

Dear C++ programmers,

I have 2 classes
A and B
with virtual functions
virtual long A::Save();
virtual long B::Save(bool b = true);

Now, if I have a Pointer A * which points to a B Object:

B b;
A * p = & b;
p->Save();

Unfortunately A::Save() is called but I wanted B::Save() to be called.
In this case, the default parameter of B::Save() is senseless - but the
compiler gives no error.

???

Greetings
Ernst
 
G

Gianni Mariani

Ernst said:
Dear C++ programmers,

I have 2 classes
A and B
with virtual functions
virtual long A::Save();
virtual long B::Save(bool b = true);

Now, if I have a Pointer A * which points to a B Object:

B b;
A * p = & b;
p->Save();

Unfortunately A::Save() is called but I wanted B::Save() to be called.
In this case, the default parameter of B::Save() is senseless - but the
compiler gives no error.

This is exactly what the language specifies. For the "B::Save" method
to be called you need to have a "B * p;" i.e. a pointer to a B object.

However, you could theoretically do this:

class B
{
.....
virtual long Save() { Save( true ); }
virtual long Save(bool b);

};

Now you get what you expect. Here we have overloaded "Save()" and made
it do what you expect p->Save() to do.

G
 
V

Victor Bazarov

Ernst Murnleitner said:
Dear C++ programmers,

I have 2 classes
A and B
with virtual functions
virtual long A::Save();
virtual long B::Save(bool b = true);

B::Save is not an overrider for A::Save. They have different
types. Default argument values are not part of the function
type.
Now, if I have a Pointer A * which points to a B Object:

B b;
A * p = & b;
p->Save();

Unfortunately A::Save() is called but I wanted B::Save() to be called.

You have to make B::Save to be the overrider of A::Save. In
order to accomplish that you need to make them the same type.
Either give A::Save the argument or remove the argument from
B::Save.
In this case, the default parameter of B::Save() is senseless - but the
compiler gives no error.

This should help you:

class A {
public:
virtual long Save();
};

class B {
long Save(bool b); // not virtual and private
public:
virtual long Save() { this->Save(true); }
};

int main() {
B b;
A *p = &b;
p->Save(); // will call B::Save(), which in turn will call
// B::Save(bool)
}

HTH

Victor
 
R

Ron Natalie

Ernst Murnleitner said:
Dear C++ programmers,

I have 2 classes
A and B
with virtual functions
virtual long A::Save();
virtual long B::Save(bool b = true);

Now, if I have a Pointer A * which points to a B Object:

B b;
A * p = & b;
p->Save();

Unfortunately A::Save() is called but I wanted B::Save() to be called.
In this case, the default parameter of B::Save() is senseless - but the
compiler gives no error.

B::Save(bool) doesn't override A::Save. There's no way that this is going
to happen. You must match the parameter list if you want things to override.
Further, a function in the derived class hides the base class definitions so
B::Save(bool b = true) is possibly not senseless.

The compiler issues no error because there is no error.
 
S

SK

Ron Natalie said:
B::Save(bool) doesn't override A::Save. There's no way that this is going
to happen. You must match the parameter list if you want things to override.
Further, a function in the derived class hides the base class definitions so
B::Save(bool b = true) is possibly not senseless.

The compiler issues no error because there is no error.
Please correct me in my understanding of hiding and overriding of member
functions.
A function gets overridden when a derived class defines a function with the
same name, return type and
parameters as a base class function.
A function gets hidden when a derived class defines a function with the same
name but different return type or
parameters.
Now my question is that in the OP's code snippet doesn't B::Save hide
A::Save ?
If that is the case then why does the compiler not issue any error message?

-SK
 
K

Karl Heinz Buchegger

SK said:
Now my question is that in the OP's code snippet doesn't B::Save hide
A::Save ?
If that is the case then why does the compiler not issue any error message?

Because p is a pointer to A. And A has a Save() method.

For
A* p = &b;
p->Save();

it is completely unimportant that there exists a B class. The B class
is never investigated, if it contains a member function Save().
 
S

SK

Karl Heinz Buchegger said:
Because p is a pointer to A. And A has a Save() method.

For
A* p = &b;
p->Save();

it is completely unimportant that there exists a B class. The B class
is never investigated, if it contains a member function Save().
Please correct me again if I am wrong.
Do you mean to say that p is statically a pointer to A(even if it's
pointing to B) and B has no matching definition for Save() so the function
name becomes
visible.
Also
B b;
b.Save () //error

Thanks again.
-SK
 
K

Karl Heinz Buchegger

SK said:
Please correct me again if I am wrong.
Do you mean to say that p is statically a pointer to A(even if it's
pointing to B)

When the compiler tries to compile

p->Save();

it looks up the data type of p. And that's A*

Thus class A is searched for a member function Save().

The fact that during *runtime*, p in reality points to a B object
is unimportant for the compiler. It cannot know this in general.
and B has no matching definition for Save() so the function
name becomes
visible.

No. B is never looked up to figure out which function to call.
In
p->Save();
there is no logic path that would lead to a class B. In that
statement there is only class A (which is the data type of *p)
mentioned.
Also
B b;
b.Save () //error

This is different. Here the compiler knows that b is of type B.
Thus the function lookup starts in the B class.
 
R

Roel Schroeven

SK said:
I agree with you completely that at compile time p's type is determined as
A*.
But since Save () is a virtual function the function call gets resolved to
VtablePtr->Save, the actual function call is then evaluated at run time.
I hope I am right so far :).
Yes.

At run time(in the OP) B object's Vtable is being referred to at run time.
A* p = &b;
p->Save ()
(I am not very sure after this :-( )
In this Vtable the function pointer being referred to is A's Save method.

Yes. If the signature of the method in B would have been the same as the
method in A, the function pointer would have referred to B's Save method
instead.
 
S

SK

Roel Schroeven said:
method.

Yes. If the signature of the method in B would have been the same as the
method in A, the function pointer would have referred to B's Save method
instead.
Thanks Karl and Roel for your inputs.
I know VTables are implementation specific.
Still if you could suggest any useful links/resources on VTables, that would
be great.

Thanks,
-SK
 
K

Karl Heinz Buchegger

SK said:
I agree with you completely that at compile time p's type is determined as
A*.
But since Save () is a virtual function the function call gets resolved to
VtablePtr->Save, the actual function call is then evaluated at run time.
I hope I am right so far :).

Right. But we were discussing why this is not a compile-time error.
Thus we don't have to deal with runtime issues.
At run time(in the OP) B object's Vtable is being referred to at run time.
A* p = &b;
p->Save ()
(I am not very sure after this :-( )
In this Vtable the function pointer being referred to is A's Save method.

Again: Right.
P.S : I hope I am not asking too many and too silly questions :).

There are no silly questions. :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,043
Latest member
CannalabsCBDReview

Latest Threads

Top