I have structs that just contain data, a minimal example would be
struct A{
int a;
};
struct B{
int a;
int b;
};
I realized now after using these two structs that A is always should be a subset of B. Because of this, I would like to couple the structs together, so any change in A is reflected in B.
The most obvious way to do this is with inheritance, so just
struct B: public A{
int b;
};
However, I don't want any accidental object slicing, so I also want for B to not visibly subtype A. Basically, I don't want users to know that B extends A, it should be hidden as an implementation detail.
I know that the standard is "favor composition over inheritance", but that would make it so accessing the fields of B would be like "B.inner.a", which I don't really want for various reasons. Like I stated before, I want the knowledge that B is a superset of A to be an implementation detail.
So far, the only things I know about C inheritance is that it can be public, protected, or private, but none of those modifiers help me here. Is there any language features or standard practices that can help me here?
CodePudding user response:
Explicitly deleting the appropriate constructor and assignment operator will be sufficient if the goal is to prevent object slicing.
struct B;
struct A{
int a=0;
A();
A(const B &)=delete;
A &operator=(const B &)=delete;
};
struct B : A {
int b=0;
};
B b1, b2;
A a1, a2;
void foo()
{
b1=b2; // Ok.
a1=a2; // Ok.
a1=b1; // Error.
B b3{b2}; // Ok.
A a3{a2}; // Ok.
A b4{b1}; // Error
}
The only downside is loss of convenient aggregate initialization, that will need to be remedied with explicit constructors.
CodePudding user response:
You can use private inheritance, but then make A::a
public:
struct B : private A {
using A::a;
int b;
};
(With the appropriate constructors added since B{1, 2}
will no longer work without it)