c++optimizationprivate-inheritance

C++ can (virtual) private base classes be removed by the compiler?


Given the following example:

class A
{
    protected:
        static void useful_function_without_side_effects() {...}
}

class B : private A
{
    // B has no friends :(

    public:
        void travel_back_in_time() { super_useful_function(); }
}

Question 1: Would it be allowed for the compiler to optimize the base class A out, since this base class can't really affect B or it's run-time behaviour in any way?

Question 2: Would this change if the inheritance would be declared private virtual like this?

class B : private virtual A

Solution

  • Answer 1:

    Non-polymorphic classes have completely no representatives in runtime at all. The only things that may exist are objects and methods, which are seen as functions. The class only instructs the compiler to access parts of the object and resolve method calls the way as defined. Once resolved directly, everything is hard-coded in the runtime code. The private qualifier doesn't change anything here.

    The A class (that has no fields) derived by B does not "add size" to the object of class B, should that be your question. This is always true if A class has no fields, but sizeof(A) will be always 1 at least. Although there's also no such rule that the size of B must be a sum of sizes of all fields and base classes.

    Answer 2

    This adds size to the B class. The standard doesn't precise what way. In typical implementations it will always extend the size of the B class by a size of one pointer, plus any possible size of class A.

    Typically virtual inheritance is implemented with the use of "pointer to itself". That is, the subobject of derived class (A) is physically part of the overall object, but it's never accessed directly, but through a pointer in the overall object.

    This is more-less the situation when you have fieldless A and B with fields of total size 4:

    Physical inheritance:

    B: [A: 0] [B extension: 4]
    

    Virtual inheritance:

    B: [A virtual: <pointer size>] [B extension: 4] [A shared subobject: 1]
    

    The order of these things may differ between implementations, although it's part of the ABI definition, not compiler's private rule (that is, all compilers on one platform must use the same rules).