开发者

Linking fails when missing implementation of a not-used pure virtual method

I have a class, which inherits from a class with a pure virtual functions.

Now I need to add another class, which doesn't need some method. I got an idea not to implement this method, instead of always throwing an exception when this method is called, like in the next example :

#include <iostream>

class ibase {
    public:
        virtual void foo() = 0;
        virtual void boo() = 0;
};

class base1 : public ibase {
    public:
        virtual void foo(){ std::cout<<"base1::foo"<<std::endl; }
        virtual void boo(){ std::cout<<"base1::boo"<<std::endl; }
};

class base2 : public ibase {
    public:
        virtual void foo() { std::cout<<"base2::foo"<<std::endl; }
        virtual void boo();
};

int main()
{
    ibase *inst1 = new base1;
    ibase *inst2 = new base2;

    inst1->foo();
    inst1->boo();
    inst2->foo();
}

But when I tried to compile using next compiler options :

g++ dfg.cpp  -ansi -pedantic -Wall

this example produced next output (using g++ 4.3.0) :

/tmp/ccv6VUzm.o: In function `base2::base2()':
dfg.cpp:(.text._ZN5base2C1Ev[base2::base2()]+0x16): undefined reference to `vtable for base2'
collect2: ld returned 1 exit status

Can someone explain why the linking fails? The method boo() is not called.开发者_如何学C


The vtable for base2 is created - you use a base2. The vtable references boo() - so you need to define it.

10.3/8:

A virtual function declared in a class shall be defined, or declared pure (10.4) in that class, or both; but no diagnostic is required (3.2).


The One-Definition Rule states that each function that is used must be defined exactly once. The definition of the term used includes the following line:

a virtual function is used if it is not pure

That means that all non-pure virtual functions have to be defined even if they aren't called


It fails because the internal vtable needs a place to point to. It doesn't matter if it is called, the vtable is still created.

Create an empty body for the method and you should be good to go.


You have to implement the method in base2, there is no way around it. Polymorphism is a run time behavior, and there is no way for the linker to know that boo will never be called. You can simply provide a dummy implementation in the base class instead of making it pure virtual if its not mandatory to implement the method in derived class.


boo may not be invoked in reality but it is used to construct the v-table for base2.

You have to define what behaviour will happen is someone has a base2 and calls boo() on it (via its base class pointer) even if there is no point in the code where this is actually invoked. It is part of the contract of implementing an ibase.

The design is of course flawed, and if you want a class that allows a foo only there should be an interface for that.

If your particular instance is that a call is a no-op then that IS a behaviour for the class.


You just forgot to implement virtual void base2::boo (). You have to implement it in order to instantiate base2 class. Otherwise you can leave it pure-virtual by not declaring it in base2 class.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜