What would be the output? and Why?

V

Vikram

class Base
{
public:
virtual ~Base(){}
virtual void NeedNothing( int speed = 10 )
{
cout << speed;
}
};

class Child: public Base
{
public:
virtual ~Child(){}
virtual void NeedNothing( int speed = 100 )
{
cout << speed;
}
};

void main()
{
Base* p = new Child;
p->NeedNothing();
delete p;
}

BRs,
 
R

Ron Natalie

Vikram wrote:

Doesn't output anything, the program is ill-formed.

void main()

main must return int.
{
Base* p = new Child;
p->NeedNothing();

Defalut args is a compile-time thing. The call here is to
Base::NeedNothing, so the default arg is 10. The subsitution
of the overriding virtual function happens at the last point
of the calling procedure (after the name is looked up, overloading
is considered, access control is checked, and the arguments are
evaluated).
 
L

Lionel B

Vikram said:
class Base
{
public:
virtual ~Base(){}
virtual void NeedNothing( int speed = 10 )
{
cout << speed;
}
};

class Child: public Base
{
public:
virtual ~Child(){}
virtual void NeedNothing( int speed = 100 )
{
cout << speed;
}
};

void main()
{
Base* p = new Child;
p->NeedNothing();
delete p;
}

There would be no output. The code would fail to compile (try it).
 
K

Krishanu Debnath

Vikram said:
class Base
{
public:
virtual ~Base(){}
virtual void NeedNothing( int speed = 10 )
{
cout << speed;
}
};

class Child: public Base
{
public:
virtual ~Child(){}
virtual void NeedNothing( int speed = 100 )
{
cout << speed;
}
};

void main()
{
Base* p = new Child;
p->NeedNothing();
delete p;
}

BRs,

It'll take the value from Base Class's virtual function declaration.

Sec 8.3.6, Para 10

"A virtual function call (class.virtual) uses the default arguments in
the declaration of the virtual function determined by the static type of
the pointer or reference denoting the object."

Krishanu
 
D

David White

Vikram said:
class Base
{
public:
virtual ~Base(){}
virtual void NeedNothing( int speed = 10 )
{
cout << speed;
}
};

class Child: public Base
{
public:
virtual ~Child(){}
virtual void NeedNothing( int speed = 100 )
{
cout << speed;
}
};

void main()

int main()
{
Base* p = new Child;
p->NeedNothing();
delete p;
}

The output is "10", because the static type is used to determine the default
argument before the dynamic type is used to determine the function to call.
For consistency it has to be that way because the class definition for Child
isn't necessarily even visible to the compiler when a virtual function of
Base overridden by Child is called.

This wasn't homework was it?

DW
 
V

Vikram

OOPS! Sorry abt that void main..
But my doubt is,
If you insert a line,

cout << "In Child" ; inside the NeedNothing() of Clild,

It will print 10 In Child
That means, It will use the value 10 ( Base class value) but it calls the
Child::NeedNothing();

Can someone explain me the logic behind this?

Regards,
V
 
K

Karl Heinz Buchegger

Vikram said:
OOPS! Sorry abt that void main..
But my doubt is,
If you insert a line,

cout << "In Child" ; inside the NeedNothing() of Clild,

It will print 10 In Child
That means, It will use the value 10 ( Base class value) but it calls the
Child::NeedNothing();

Can someone explain me the logic behind this?

Default arguments are always bound at *compile time*, while
the virtual function call is dispatched at runtime.

So the only thing the compiler knows about when
compiling

p->NeedNothing();

is that p points to some object derived from Base.
It doesn't know which one exactly, but it knows that the
virtual function in Base takes 10 as default argument.
Thats what gets compiled.
 
R

Ron Natalie

Vikram said:
OOPS! Sorry abt that void main..
But my doubt is,
If you insert a line,

cout << "In Child" ; inside the NeedNothing() of Clild,

It will print 10 In Child
That means, It will use the value 10 ( Base class value) but it calls the
Child::NeedNothing();

Can someone explain me the logic behind this?
I already did. The evaluation of the args occurs with the
(static) type of the call as does just about EVERYTHING else
with regard to the call. The only thing that happens dynamically
is the substitution of the actual invocation of the overriding
function.

For example:

class Base {
private:
virtual void private_in_base();
public:
virtual void foo(int i);
};

class Derived : public Base {
private:
void foo(int i);
viod foo(double d);
public:
void private_in_base();
};

int main() {
Base* b = new Derived;

b->private_in_base(); // ILLEGAL, Base::privateInBase private
b->foo(1); // Legal Base::foo(int) is public
b->foo(1.5); // ultimately invokes Derived::foo(int)
}

As shown above, name lookup, overloading, and access control are all
done with respect to the (static) type of the operand.

There are only a few things that actually look at dynamic type:
dynamic_cast, typeinfo, delete, and the checking to see if the
invocation of a base class function should invoke an overrider.
 
H

Howard

Ron Natalie said:
Vikram wrote:

Doesn't output anything, the program is ill-formed.



main must return int.


Defalut args is a compile-time thing. The call here is to
Base::NeedNothing, so the default arg is 10. The subsitution
of the overriding virtual function happens at the last point
of the calling procedure (after the name is looked up, overloading
is considered, access control is checked, and the arguments are
evaluated).

That's very strange! :) I don't dispute it, but it's certainly not
intuitive. Suppose one wanted polymorphic behavior regarding the
parameter...how would one accomplish having a different default parameter in
the two functions (base and derived versions)? I don't know when I would
need it, but it seems like something that would be useful, somewhere.

One solution would be to have a member variable that is set in the
constructors, and use that whenever some "special" value is detected as the
parameter (and make that special value the default value for the parameter).
But that requires having such a "special" value available, and such may not
be the case.

Another alternative might be to forego the default parameter value, and
instead have a second (virtual) function with no parameter, whose job is to
call the first function with the parameter value that the specific class
requires.

That second one sounds better to me, unless you're worried about the
function call overhead I suppose. Thoughts?

-Howard
 
K

Karl Heinz Buchegger

Howard said:
That's very strange! :) I don't dispute it, but it's certainly not
intuitive.

Maybe not for you.
For me it is intuitive in that the compiler simply substitutes a missing
argument when processing the call *at compile time*. It is a little bit
similar to macro-preprocessing in that it can be done by modifying the
'source code' that gets eventually compiled.
Suppose one wanted polymorphic behavior regarding the
parameter...how would one accomplish having a different default parameter in
the two functions (base and derived versions)? I don't know when I would
need it, but it seems like something that would be useful, somewhere.

One solution would be to have a member variable that is set in the
constructors, and use that whenever some "special" value is detected as the
parameter (and make that special value the default value for the parameter).
But that requires having such a "special" value available, and such may not
be the case.

Much to complicated.
A default argument can always be substituted by having 2 functions where one
calls the other and inserts the missing argument.
Another alternative might be to forego the default parameter value, and
instead have a second (virtual) function with no parameter, whose job is to
call the first function with the parameter value that the specific class
requires.

That second one sounds better to me, unless you're worried about the
function call overhead I suppose. Thoughts?

Thats the way to do it.

class Base
{
public:
virtual void foo() { foo2( 10 ); }
void foo( int i ) { foo2( i ); }

virtual void foo2() { /* this is the virtual function */ }
};

class Derived
{
public:
virtual void foo() { foo2( 20 ); }

virtual void foo2() { /* whatever you want */ }
};
 

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

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top