Question

I'm reading Thinking in C++ by Bruce Eckel. In Chapter 15 (Volume 1) under the heading "Behaviour of virtual functions inside constructor", he goes

What happens if you’re inside a constructor and you call a virtual function? Inside an ordinary member function you can imagine what will happen – the virtual call is resolved at runtime because the object cannot know whether it belongs to the class the member function is in, or some class derived from it. For consistency, you might think this is what should happen inside constructors.

Here Bruce's trying to explain that when you call a virtual function inside an object's constructor, polymorphism isn't exhibited i.e. the current class' function will only be called and it will not be some other derived class version of that function. This is valid and I can understand it, since the constructor for a class will not know beforehand if it's running for it or for someother dervied object's creation. Moreover, if it does so, it'll be calling functions on a partially created object, which is disastrous.

While my confusion suddenly arose because of the first sentence where he states about the ordinary member function, where he says the virtual call will be resolved @ run-time. But wait, inside any member function of a class, when you call another function (be it virtual or non-virtual) it's own class version will only be called, right? E.g.

class A
{
    virtual void add() { subadd(); }
    virtual subadd() { std::cout << "A::subadd()\n"; }
};

class B : public A
{
    void add() { subadd(); }
    void subadd() { std::cout << "B::subadd()\n"; }
};

In the above code, in A::add() when a call to subadd() is made, it'll always call A::subadd() and the same holds true for B as well, right? So what is he meaning by "the virtual call is resolved at runtime because the object cannot know whether it belongs to the class the member function is in, or some class derived from it" ?

Is he explaining it with respect to a call via a base class pointer? (I really suspect so) In which case he shouldn't be writing "Inside an ordinary member function"; from my understanding so far, any call of a member function from inside another member function of the same class is not polymorphic, please correct me if am getting it wrong.

Was it helpful?

Solution

You are wrong - a further derived class could override some of the virtual functions, meaning that a static call would be wrong. So, to extend your example:

class C : public B
{
public:
    // Not overriding B::add.
    void subadd() { std::cout << "C::subadd\n"; }
};

A *a = new C;
a->add();

This dynamically calls B::add, which in turn dynamically calls C::subadd. A static call to B::subadd would be wrong, since the dynamic type is C and C overrides the function.

In your example, the duplication of A::add as B::add is unnecessary - both will call subadd polymorphically whatever the dynamic type of the object.

OTHER TIPS

when you call another function (be it virtual or non-virtual) it's own class version will only be called, right?

Sorry, wrong. The constructor is the exception. Otherwise, you are dealing with a fully constructed object for which full polymorphism is in place. In your later example (if B inherits from A), what is called is the B::subadd() (just take the code for a test drive: that's really the best way to learn how a programming language works).

The call subadd(); in your examples is really the call this->subadd();. In A::add(), the type of this is A*, but this might point to a C object (assuming C derives from A too). When compiling A::add(), the compiler can't know which virtual functions are overridden in class C. The call this->subadd(); in A::add() may actually call C::subadd(). Thus, the compiler has no choice but putting in a virtual call, to be resolved at runtime when it knows where this-> points to.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top