Reputation: 41
I was asked by my friend a virtual function problem.
If a child object call a virtual function, under what condition, this virtual function is actually executed the one in the father's implementation?
Upvotes: 2
Views: 394
Reputation:
Answer has already been provided, this may happen during construction:
It might also be a funny source of run-time errors, so pay special attention to constructors & pure virtual methods calls in the base class ;)
http://support.microsoft.com/kb/125749
class A;
void fcn( A* );
class A
{
public:
virtual void f() = 0;
A() { fcn( this ); }
};
class B : A
{
void f() { }
};
void fcn( A* p )
{
p->f();
}
// The declaration below invokes class B's constructor, which
// first calls class A's constructor, which calls fcn. Then
// fcn calls A::f, which is a pure virtual function, and
// this causes the run-time error. B has not been constructed
// at this point, so the B::f cannot be called. You would not
// want it to be called because it could depend on something
// in B that has not been initialized yet.
B b;
void main()
{
}
Upvotes: 0
Reputation: 63704
Base::f();
)Upvotes: 1
Reputation: 320371
It is impossible to understand what exactly is implied by the question in ts current form.
If taken literally, the question has an obvious and immediate answer: the parent's version is called if the parent's implementation is the final overrider for the function in question, i.e. if the child provides no implementation of its own
class parent {
public:
virtual void foo() { /* whatever */ }
};
class child : parent {
public:
void bar() {
foo(); /* call the parent's implementation, as requested */
}
};
So, here's your answer.
Of course, it's intuitively obvious to anyone that most likely that's not what was implied by the question. Quite likely it was implied that the child class overrides the parent's function. In that case there's another obvious answer: the parent's version will be called if the child uses a fully-qualified name of the function
class parent {
public:
virtual void foo() { /* whatever */ }
};
class child : parent {
public:
virtual void foo() { /* whatever */ }
void bar() {
parent::foo(); /* call the parent's implementation, as requested */
}
};
Another possible answer is that the object for which the function is called actually has parent
type (since nowhere in the question it says that the child should call it for this
object)
class parent {
public:
virtual void foo() { /* whatever */ }
};
class child : parent {
public:
virtual void foo() { /* whatever */ }
void bar() {
parent p;
p.foo(); /* call the parent's implementation, as requested */
}
};
Again, it feels intuitively that this is not what the question is about. Most likely, the question was intended to be about virtual calls made from constructors and destructors
class parent {
public:
parent() {
foo(); /* always calls `parent::foo` */
}
virtual void foo() { /* whatever */ }
};
class child : parent {
public:
child() : parent() /* `parent::parent` will call `parent::foo` */
{}
virtual void foo() { /* whatever */ }
};
However, for that the question is incorrectly worded. In the last example at the moment of the call, the child object does not exist yet. The memory for it is already allocated but its lifetime hasn't started yet. It is incorrect to say that the call to the virtual function is performed by the child object. It is performed by the parent object.
So, to resume the above: the question is so ambiguously and vaguely worded, that it doesn't make any sense in its current form.
Upvotes: 2
Reputation: 375484
If the child class' destructor has already been called, then the object is now of the parent's type, so the parent's virtual functions will be called.
Upvotes: 0
Reputation: 2426
If this invocation is whithin a constructor, the dispatch will be static. Read this for more info: http://cplusplus.co.il/2009/09/30/virtual-dispatching-within-a-constructor-or-a-destructor/
Here's the example from the article I've linked to:
struct A {
A () { f(); }
virtual void f () { }
};
struct B : A {
B () :member(0) {}
void f () { std::cout << member; }
private:
int member;
};
int main () {
B b;
return 0;
}
The invoked f is A::f, despite the fact that it is virtual and called by an object of type B who has its own implementation.
Upvotes: 0
Reputation:
I think you need to post some code to clarify what you are asking, but (with the exception of the destructor) the base class function will not be called unless the child calls itt explicitly from its own function. For example, in:
struct A {
virtual ~A() {}
virtual void f() {}
};
struct B : public A {
virtual void f() {}
};
int main() {
A * a = new B;
a->f();
delete a;
}
only B's virtual function f() is called. If you wanted A::f() to be called you would have to do so explicitly:
struct B : public A {
virtual f() {
A::f(); // explicit call
}
};
Oh, and of course in the case when B does not declare the function - in this case A::f() will always be called.
Upvotes: 4