Search code examples
c++visual-studio-2010inheritanceg++virtual-destructor

Same program behavior is different in g++ & MSVS 2010


I was reading this. The accepted answer of the linked question contains following code:

class Base
 {
    private:
        virtual ~Base() = 0;   /* A */
 };

 class Derived : protected virtual Base
 {
    private:
     ~Derived () {.......}    /* B */
 };

I tried this program in g++ 4.8.1, 4.9.2 & MSVS 2010 compiler (see live demo here.). But g++ 4.8.1 & 4.9.2 gives me an compiler error while MSVS 2010 compile it without any error. Clang also gives an error see here.

So, why g++ shows error message? I haven't created an object of derived class. So, I think it shouldn't give compilation error & MSVS 2010 is correct.

But why both this compiler behaves differently?

Which compiler is right regarding behavior of this program? Is this bug in any of these compilers or something other?

I am indeed getting confused.

Your help will be highly appreciated.


Solution

  • I would argue that g++ and clang (and VS2012) are correct. And that VS2010 is incorrect.

    Essentially, to destruct an instance of Derived, the compiler must determine if the destructor of Base is accessible. A private destructor of a base class is not accessible to the derived class, so Derived cannot be destructed.

    I would suggest this does not require that the class be instantiated. Under the "separate compilation" model, a compiler must assume that some other compilation unit (invisible to the compiler when compiling this compilation unit) will instantiate and/or destroy an instance of the class. Which means it should check/compile/emit code for the destructor in every compilation unit which has visibility of the definition of that destructor.

    Rules related to the "separate compilation" model are among those known informally as "as if" rules - an implementation must act as if it follows each rule, even if it does things differently under the hood.

    The thing is, the various "as if" rules are where compiler vendors often take shortcuts - in the interests of speed of compilation, or other things.

    This is only one possible explanation of why VS2010 is getting it wrong.

    The upshot is that VS2010 is not properly checking accessibility of destructors in such cases. Older Microsoft C++ compilers were quite notorious for being less than fully standard compliant. In recent years, Microsoft has strategically sought to improve their conformance with the standard, but it takes time for such things to flush out. This would be consistent with the observation that VS2010 does not complain, but VS2012 (like other compilers) does.

    One possible explanation of this is that VS2010 does not fully comply with requirements of "separate compilation". Another is that is simply takes shortcuts when checking accessibility of private members in base classes. To determine if either of these - or something else - is the explanation, it would probably be necessary to dig into details of how VS2010 is implemented.