0

TL;DR Old code I am referencing is not compliant with C++. It's amazing the code ever worked. You cannot call virtual methods in constructors and deconstructors.

A peer and I had a discussion about the virtual keyword in C++. On an older ubuntu OS I was working on a program that reported errors about calling "pure virtual methods" which should not have happened

class Base {
    virtual ~Base() { this->DoSomethingElse(); }
    virtual bool DoSomething() = 0;
    virtual bool DoSomethingElse() = 0;
};

class Foo : public Base {
    ~Foo();
    bool DoSomething();
    bool DoSomethingElse();
};

// Later...
Base* obj = new Foo();
obj->DoSomething(); // Pure virtual function called SIGABORT
delete obj; // Pure virtual function called SIGABORT

After stepping through a debugger, I finally I added virtual on the inherited classes

class Base {
    virtual ~Base() { this->DoSomethingElse(); }
    virtual bool DoSomething() = 0;
    virtual bool DoSomethingElse() = 0;
};

class Foo : public Base {
    virtual ~Foo();
    virtual bool DoSomething();
    virtual bool DoSomethingElse();
};

// Later...
Base* obj = new Foo();
obj->DoSomething(); // Ok!
delete obj; // Ok!

I double checked google for anything that could suggest virtual was needed on inherited classes before telling my peer. They said that yes, virtual is needed in the standard but that compilers automatically fill virtual in for inherited classes most of the time. From my understanding (and I believe most programmers) virtual is needed when you want to override that function via polymorphism. But it was not clear that you need to mark child class function implementations too.

I'm suprised by the lack of resources on the topic. So what is it? Is virtual implied in modern C++ compilers and where does the standard describe that?

Dan
  • 1,812
  • 3
  • 13
  • 27
  • you might find this interesting: https://stackoverflow.com/questions/39932391/virtual-override-or-both-c – Mat Oct 08 '18 at 18:57
  • Mat this post wasnt about overrides. – Dan Oct 08 '18 at 19:19
  • Well you seemed confused enough about whether virtual was needed when overriding, so seemed like a post specifically about `virtual` vs `override` would have interested you. Sorry for the noise then. – Mat Oct 08 '18 at 19:22
  • if you read it you'd see I'm not confused. You are confused by the question. My program CRASHED without explicitly defining virtual member functions in the inherited class. – Dan Oct 08 '18 at 19:23
  • 1
    Sorry again for the noise, but [mcve] please. The code you posted can't compile at all. (Private constructors. Missing destructors and implementations of virtuals.) And modernish compiler flags the destructor in the base. – Mat Oct 08 '18 at 19:35

1 Answers1

3

A function that overrides a virtual function is virtual. That's not the problem here.

The problem is the call to DoSomethingElse() (with or without the redundant this->) in the destructor for Base. When a constructor or destructor calls a virtual function it dispatches to the version of the function that belongs to the class whose constructor or destructor is being called, not to the version for a class derived from that class. So that call in the destructor calls Base::DoSomethingElse(), which is a call to a pure virtual function, and that's why the runtime aborts.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
  • Interesting point. So the code I'm referencing dates to 1993 and they used this nomenclature often in software. What's the modern work around? – Dan Oct 08 '18 at 20:53
  • 1
    There is no workaround. There is no derived object. Calling member functions on an object that has not been constructed or has already been destructed doesn’t make sense. – Pete Becker Oct 08 '18 at 21:56
  • It seems you are right. I am now on a newer machine with latest tools. The compiler not only gives me a warning but fails to compile. I'm surprised this software ever worked. This nomenclature has been published in a few C++ books back in the early 90s. – Dan Oct 08 '18 at 22:03
  • @Maverick -- don't know if this helps, bit the rule is that not providing a definition for a virtual function that is not pure virtual is an error, but the compiler is not required to diagnose it if the function is not actually called. – Pete Becker Oct 09 '18 at 14:40