Tristan Brindle
Tristan Brindle

Reputation: 16824

Legally invoking a pure virtual function

I'm sure we've all seen code that crashes due to a bug that results in a pure virtual function being called. One simple example is like this:

struct Base
{
    Base() { method(); }

    virtual void method() = 0;
};

struct Derived : Base
{
    void method() {};
};

int main()
{
    Derived d;
}

In this case, the call to method() in the Base constructor is specifically cited as undefined behaviour by section 10.4/6 of the C++ standard, so it's no surprise that we end up crashing. (Both g++ and Clang warn about this, and in fact linking fails with g++ with this example, though Clang succeeds.)

But, just for fun, can anybody come up with a way to invoke a pure virtual function which does not rely on undefined behaviour?

(I suppose you could argue that if such a method exists then there's a defect in the C++ standard, but I'm just curious...)

EDIT: Several answers guys and thank you, but I should have made it clear that I realise it's legal to make a non-virtual call to a pure virtual function (providing a definition exists somewhere). I was more wondering whether there is any clever loophole in the laws which could result in a virtual call, and thus most likely a crash in the common case of having no definition.

For example, perhaps via multiple inheritance one could perform some clever (legal) cast, but end up with the "wrong" (unimplemented) PV method() being called, that sort of thing. I just thought it was a fun brainteaser :-)

Upvotes: 10

Views: 337

Answers (4)

knivil
knivil

Reputation: 906

A pure virutal function can have an implementation. Best example: a pure virtual destructor must have an implementation because all destructors will be called when an an object is destroyed.

Upvotes: 2

Mike Seymour
Mike Seymour

Reputation: 254431

It's perfectly legal to call a pure virtual function non-virtually:

Derived d;
d.Base::method();

Of course, this requires the function to be defined, which isn't the case in your example.

Upvotes: 5

Depends on what you mean with possible. Here's one which compiles successfully, but will most likely result in a linker error:

struct Base
{
    virtual void method() = 0;
};

struct Derived : Base
{
    void method() { Base::method(); };
};

int main()
{
  Derived d;
  d.method();
}

Live example

It compiles because nothing prevents a pure virtual function from actually having a body as well. That can be provided in the same translation unit (in a separate definition), or in a different translation unit. That's why it's a linker error and not a compiler one - just that the function has no body here doesn't mean it doesn't have one elsewhere.

Upvotes: 2

rubenvb
rubenvb

Reputation: 76519

Taking out the linker error from @Angew's answer. Not sure about the undefined behavior happening here...

struct Base
{
    virtual void method() = 0;
};

void Base::method(){}

struct Derived : Base
{
    void method() { Base::method(); };
};

int main()
{
  Derived d;
  d.method();
}

Live Demo

Upvotes: 0

Related Questions