inheritance - Limit object sharing of virtual base classes in C++ -
i know physical , virtual inheritance in c++. however, know if model somehow achieved design patterns or tricks.
the classes e , f , bases of should not modified.. imagine come extern library.
everything below e , f open. ok introduce intermediate helping classes, non-member function, templates... realize this:
baseclass / \ / \ / \ / \ / \ / \ b c b d \ / \ / \ / \ / e f \ / \ / \ / finalclass
note e , f shall not share a. finalclass should indeed contain 2 a. problem is, creation of e or f require, b, c , d inherit virtually.. however, if virtual base class, compiler create 1 object in finalclass instead of 2 different ones.
so, think many of recommend composition instead of inheritance here. however, composition modells "has a"-relationship here , not "is a"-relationship. in explaination, finalclass behave e or f, including being able convert classes.
this layout not feasible in c++, additional helping class.
the fact that b inherits a, , want share inheritance c on 1 side , d on other, requires b, c , d virtually inherit a. shared accross both branches of diamond.
alternatives
what alternatives there ?
if you'd manage break sharing of between left , right branches of diamonds, break sharing of common base.
if you'd introduce intermediary classes a1, a2 implementing left , right share in branches, you'd stuck fact both b have inherit either 1 or other
the way out have duplicate class b.
this last solution doesn't fulfill requirement follows:
struct base { int x; }; struct : public virtual base { int a; }; struct ac : public a{}; // synonym struct b : public virtual { int b; }; struct bc : public virtual ac { int b; }; // !! clone !! struct c : public virtual ac { int c; }; struct d : public virtual { int d; }; struct e : public bc, c { int e; }; struct f : public b, d { int f; }; struct final : public e, f { };
and here access memebers:
final f; f.x = 2; // unambiguous: there's onely 1 of f.f = 1; f.e = 2; f.d = 3; f.c = 4; //f.b = 5; // ambiguous: there 2 of f.e::b = 5; // successful desambiguation f.f::b = 6; // successfuldesambiguation //f.a = 7; // ambiguous: there 2 of f.e::a = 7; // successful desambiguation f.f::a = 8; // successful desambiguation
to come problem statement: can't intervene above e , f. in case options limited :
- you publicly inherit
- you privately inherit via intermediary classes
but effect same on sharing, following code desmonstrates (on top of above one) :
class fi : private f // make f private { public: void set_xa(int u, int v) { x = u; a= v; } void show_xa() { cout << "x:" << x << " a:" << << endl; } }; class ei : private e // make e private { public: void set_xa(int u, int v) { x = u; = v; } void show_xa() { cout << "x:" << x << " a:" << << endl; } }; struct final3 : public ei, public fi { }; final3 h; h.ei::set_xa(3, 4); h.fi::set_xa(5, 6); h.ei::show_xa(); h.fi::show_xa(); // shared virtually inherited memebers still shared !
conclusion:
with inheritance, you're bound design above e , f aren't allowed influence.
so first questions be:
- can't alter design after (i.e. cloning of 1 b) ?
- wouldn't unacceptable of having shered between both branches (may there's valid reason after all) ?
if answer no both questions, you'll have go composition, , implement kind of proxy design pattern, composed object proxy both components.
Comments
Post a Comment