Search code examples
c++inheritanceconst-correctness

How to expose a base class only as const reference


I want my class Foo to expose it's base class Bar only as a const reference to Bar. This would mean that the members of Bar could be read, but not set. This is what I've tried:

struct Bar
{
    int member;
};

class Foo : protected Bar
{
public:
    operator const Bar&() { return *this; }
};

But when using this, following problem arises:

int getBarMember( const Bar& bar )
{
    return bar.member;
}

int main()
{
    Foo myFoo;

    const Bar& refBar = myFoo; // C2243
    // const Bar& refBar = (const Bar&) myFoo; // always need to cast explicitly

    int read = refBar.member;

    int readByFunction = getBarMember( myFoo ); // C2243
    // int readByFunction = getBarMember( (const Bar&) myFoo ); // always need to cast explicitly
}

I want to be able to call functions that take const references to Bar without explicit casts.

The Compiler Error is:

C2243: 'conversion type' conversion from 'Foo *' to 'const Bar&' exists, but is inaccessible


Solution

  • I don't think it's possible, gcc and clang issue the following warning on the operator :

    <source>:12:5: warning: converting 'Foo' to a reference to a base class 'Bar' will never use a type conversion operator [-Wclass-conversion]
      12 |     operator const Bar&() { return *this; }
         |     ^~~~~~~~
    

    If it's possible in your real code, you could use composition over inheritance principle and do the following (see it online):

    struct Bar
    {
        int member;
    };
    
    class Foo 
    {
    public:
        operator const Bar&() { return parent; }
    protected:
        Bar parent;
    };
    

    It will probably require some changes in the way you access Bar within Foo, but it will work without casts for the outside world.