Martin Darterson
Martin Darterson

Reputation: 141

Inherit from const class

I would like to inherit from a class with the const specifier like this:

class Property
{
    int get() const;
    void set(int a);
};

class ConstChild : public const Property
{
    // Can never call A::set() with this class, even if
    // the instantiation of this class is not const
};

class NonConstChild : public Property
{
    // Can call both A::set() and A::get() depending on 
    // the constness of instantiation of this class
};

My compiler obviously gives me an error for the const keyword in the second classes declaration. Ideally I'd like to avoid having to create a new class ReadOnlyProperty from which ConstChild would inherit.

Can I somehow use the const keyword for inheritance?

Upvotes: 14

Views: 4871

Answers (8)

Nowine
Nowine

Reputation: 196

I had the same need and I ended up with this quite manual approach :

class A
{
public:

    void fooMutable(void) {}
    void fooConst(void) const {}
};

class B : private A
{
public:

    using A::fooConst;
    const A& getParent(void) const
    {
        return *this;
    }
};

void fooParent(const A&) {}

int main(void)
{
    auto b = B{};
    b.fooConst(); // Ok
    b.fooMutable(); // Fail
    fooParent(b); // Fail
    fooParent(b.getParent()); // Ok

    return 0;
}

Note that the using keyword would not work with overloads const/mutable :

class A
{
public:

    void foo(void) {}
    void foo(void) const {}
};

class B : private A
{
public:

    using A::foo; // Expose the const and the mutable version
};

To solve this you could redefine the function yourself and call the parent :

class B : private A
{
public:

    void foo(void) const
    {
        A::foo();
    }
};

It can become pretty time consuming if you're inheriting a large hierarchy, but if it's for a not-so-big class it should be very reasonable and being quite natural for the user.

Upvotes: 0

Philippe
Philippe

Reputation: 442

I had the need for a related problem, which is: to really control/highlight mutable and const access on some class. I did it with this simple reusable template wrapper:

template <typename T>
class TAccessor : private T
{
public:
    const T&    Const() const { return *this; }
    T&          Mutable() { return *this; }
};

// Example of use:
template <typename T>
using MyVector = TAccessor<std::vector<T>>;


void main()
{
    MyVector<int> vector;

    vector.Mutable().push_back(10);

    int x = vector.Const()[1];
    ...
}

Upvotes: 4

Jes&#250;s Rocha
Jes&#250;s Rocha

Reputation: 1

You can use a template class and a specialization for a constant type:

    template<typename T> class base_property {
    protected:
      T value;
    };
    template<typename T> class property : public base_property<T> {
    public:
      const T& get()const { return value; }
      void set(const T& v){ value = v; }
    };

    template<typename T> class property<const T> : public base_property<T> {
    public:
      const T& get()const { return value; }
    };

    class ConstChild : public property<const int>{ };

Upvotes: 0

Marco Amagliani
Marco Amagliani

Reputation: 147

I have a trick, not a clean solution.

class ConstChild : private Property
{
    operator const Property () { return *this; }
};

then

ConstChild cc;
cc.set(10); // ERROR
cc().get();

Upvotes: -1

Cheers and hth. - Alf
Cheers and hth. - Alf

Reputation: 145279

Use a data member or private base class instead of public base class.

Then you control the access to that member.

You can make the Property thing an abstract interface if you need polymorphic behavior.

Upvotes: 0

Jesper Juhl
Jesper Juhl

Reputation: 31465

I would like to inherit from a class with the const specifier"

However much you want to is irrelevant. You cannot. That is not valid C++.

Can I somehow use the const keyword for inheritance?"

No.

Upvotes: 0

Thomas B Preusser
Thomas B Preusser

Reputation: 1189

Introduce mutability later in your inheritance tree and derive appropriately:

class Property
{
    int get() const;
};
class MutableProperty : public Property {
{
    void set(int a);
};

And then:

class ConstChild : public Property { ... };
class MutableChild : public MutableProperty { ... };

Upvotes: 10

R Sahu
R Sahu

Reputation: 206607

If you create a const member function set, you will get what you need.

class Property
{
    int get() const;
    void set(int a);
};

class ConstChild : public Property
{
    void set(int a) const {}
};

The only caveat is that a sly user can circumvent your intention by using:

ConstChild child;
child.set(10);    // Not OK by the compiler

Property& base = child;
base.set(10);    // OK by the compiler

Upvotes: 0

Related Questions