Reputation: 141
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
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
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
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
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
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
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
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
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