2

I have two classes, base class A and derived class B. Definition as below:

Class A {
public:
    A()
    {
        ImpleDefinition();
    }
    ~A()=default:

protected:
    virtual void ImplDefinition()=0;
}

class B : public A
{
public:
    B() : A()
    {
    }
    ~B()=default;

private:
    void ImplDefinition() override
    {
        /*Some detailed implementation*/
    }
}

So when compiling this code, compiler reports "error LNK2001: unresolved external symbol" error. From code itself, I can't see I made any mistake. Interesting, if I change "ImplDefinition" from pure virtual function to virtual function.

void ImplDefinition() {};

Then everything works fine. How to explain this situation?

newcarcrazy
  • 105
  • 1
  • 7
  • What's the deal with the destructor being set to "default:"? – Saustin Sep 15 '17 at 01:29
  • Possible duplicate of [What is an undefined reference/unresolved external symbol error and how do I fix it?](https://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix) – Ken White Sep 15 '17 at 01:31

2 Answers2

3

The problem is you're calling the virtual function ImplDefinition() in A::A(). When in the constructor of the base class, the current object is always the base class subobject, the derived class part is not constructed at all; which will be performed later. Then the pure virtual A::ImplDefinition() will be called and cause the error; no dynamic dispatch here, B::ImplDefinition() won't be called at all.

Further reading about When my base class’s constructor calls a virtual function on its this object, why doesn’t my derived class’s override of that virtual function get invoked?

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
  • Really thanks for your answer. But what do I really want is calling a interface function (or virtual function) in base class constructor. Or I have to write same calling function in every derived class. Is there any code template to implement this? – newcarcrazy Sep 15 '17 at 02:15
  • @newcarcrazy You just can't do this in the constructor. You might move it to a normal member function, or change to whole design, e.g. making the class accepts an instance of the base class pointer, and call the virtual function on it; then you can pass any derived class pointer to it. – songyuanyao Sep 15 '17 at 02:28
2

You are attempting to call a pure virtual function from the constructor of the same class. Formally, the behavior is undefined. In practice it is perfectly normal to end up with a linker error for such code.

When virtual functions are called from constructors or destructors, the virtual mechanism is "capped" at the current hierarchical level: it works "up to" the class being constructed/destructed. It will never see or call any overriding virtual functions from any derived classes.

In your case the ImpleDefinition() call in the constructor of A does not see and does not call B::ImpleDefinition (contrary to what you apparently intended). Instead it attempts to call A::ImpleDefinition. And since A::ImpleDefinition is not defined, the call fails.

What you are trying to do will not work, at least in this form. You cannot "virtualize" constructor's behavior by calling virtual functions overridden in derived classes.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765