skydoor
skydoor

Reputation: 41

one question about C++ virtual function

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

Answers (6)

cmanaha
cmanaha

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

Drew Dormann
Drew Dormann

Reputation: 63704

  • When the base class's scope is explicitly used ( Base::f(); )
  • Inside the base class's constructor (because the derived object's constructor hasn't been entered yet)
  • Inside the base class's destructor (because the derived object has already been destructed)

Upvotes: 1

AnT stands with Russia
AnT stands with Russia

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

Ned Batchelder
Ned Batchelder

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

rmn
rmn

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

anon
anon

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

Related Questions