Using/storing derived member in derived class with base class that stores base member

Inductiveload

A situation I often come up against is having a set of classes, Base and Derived, where the Base class has ownership of a base-class member BaseMember, and the Derived class has a reference or pointer to the same object, but as a DerivedMember.

For example, a UI panel class that contains a specific instance of a certain type of control with some special-control functions, inheriting from a general class that contains a general control and has general-control functions.

First, say that BaseMember is inherited by DerivedMemeber.

Without using smart pointers, I might do something like this:

class Base
{
protected:
    // receive ownership but only because we say so,
    // someone else can still try to delete as it's "just a pointer"
    Base(BaseMember* _bmember):
        bmember(_bmember)
    {}

public:
    virtual ~Base()
    {
        // perform an owner's duty
        delete bmember;
    }

    // functions that might be based on BaseMember + other base state
    void SetMemberId(....) 
    {
        bmember->SetId(baz);
    }

private:
    int baz;
    BaseMember* bmember; //owned, but not smartly
}

class Derived: public Base
{
public:
    Derived(DerivedMember* _dmember):
        Base(_dmember),
        dmember(_dmember)
    {}

    // functions that only make sense for Derived + Derived/Base state
    void SetDerivedFrobulation()
    {
        // only a DerivedMember has frobulation, so only
        // Derived allows users to access it
        dmember->setFrobulation(foo);
    }

private:
    int foo; // some state
    DerivedMember* dmember; // no ownership here
}

With smart pointers (C++11 and up, specifically, I don't really care about older C++ in this case), I am tempted to do something like this and never let the Base/DerivedMember object out into dumb-pointer-land where it could leak if there was an exception somewhere inconvenient.

class Base
{
protected:
    // receive ownership
    Base(std::unique_ptr<BaseMember> _member):
        member(std::move(_member))
    {}

    virtual ~Base()
    {}

public:
    // public access functions here as before

private:
    std::unique_ptr<BaseMember> member;
}

class Derived: public Base
{
public:
    // pass the ownership down by unique_ptr
    Derived(std::unique_ptr<DerivedMember> _dmember):
        Base(std::move(_dmember)),
        dmember(_dmember.get()) // _dmember is moved! SEGFAULT if access dmember later!
    {}

    // public access functions here as before

private:
    // handy handle to the derived class so we don't need to downcast the base (or even access it!)
    DerivedClass* dmember
}

As I noted there, you can't "steal a peek" at the DerivedMember class as it comes in to the Derived constructor, because the unique_ptr is moved away before Derived gets a look in.

I can see a solution in providing a protected access to the BaseMember and static_casting back to DerivedMember in the Derived constructor (i.e. after the Base constructor is done), but this seems an ugly way to get access back to a variable we let slip though our fingers!

Another way could be each inheritor of Base owns the pointer, and base just gets a dumb pointer. In this case, the Base destructor doesn't get access to the member, as it's already gone. Also it would duplicate the ownership logic needlessly.

I think either:

  • This is symptomatic of an anti-pattern and the design of the whole Base/Derived/BaseMember/DerivedMember system is not good practice.
  • I'm missing a trick and there is a clean way to do this without fumbling a smart pointer and making a leak possible or adding functions and exposing interfaces or casting too much.

Is this a good pattern for re-use, or should I look elsewhere?

Expanding on the use case (EDIT)

In a core library, I have a class DataInterpreter which shows "some interpretation" of data - could be a string, an image, etc. This is then inherited by, amongst others, TextInterpreter which presents a string.

I then have a DataDisplayPanel class which represents a piece of UI for displaying in an abstract sense. Exactly what is in this panel will depend on the interpreter used: a TextInterpreter should get a text entry field and say a button to set some text display option, and that is handled in TextDisplayPanel, which has "special" knowledge of the text aspect of the interpreter.

There is then a DataAggregatePanel which combines a number of DataDisplayPanels and provides some global settings that affect all displays (via virtual functions), and manages the panels in a std::vector<std::unique_ptr<DataDisplayPanel> >. This aggregate class doesn't deal with any of the derived classes at all, any functions would be polymorphic and defined in the base.

In the application (which depends on the core library), these classes are extended (by inheritance or composition, whichever makes more sense). For example, if the application is a WX GUI, I might have wxDataAggregatePanel which contains wxTextDisplayPanel (and others), all of which are wxPanels. In this case, wxTextDisplayPanel might own a wxTextEntry and either own or inherit TextInterpreter and use its knowledge of the TextInterpreter's specific methods to fill the text box with a string.

Jarod42

You may use delegating constructor:

class Derived: public Base
{
public:

    Derived(std::unique_ptr<DerivedMember> _dmember):
        Derived(_dmember, _dmember.get())
    {}

    // public access functions here as before
private:
 Derived(std::unique_ptr<DerivedMember>& _dmember, DerivedMember* ptr):
        Base(std::move(_dmember)),
        dmember(ptr)
    {}
private:
    // handy handle to the derived class so we don't need to downcast the base (or even access it!)
    DerivedClass* dmember
};

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Java

Automatic conversion from derived class to base class' member variable's type

From Dev

C++: How to enforce derived class to set base member variables?

From Dev

base pointer to derived class

From Dev

inheritance data member between base and derived class c++

From Dev

returning instance of derived class from base class member function

From Dev

Why "Do not access a static member that is defined in a base class from a derived class."

From Dev

Accessing base member functions in class derived from template class

From Dev

Accessing protected member in base class from a derived class

From Dev

Derived class cannot use member pointer to protected base class member

From Dev

C++: Generic base member functions with specific types in derived class

From Dev

Calling a member function of a derived class from the base class constructor

From Dev

Accessing derived class member from base class pointer

From Dev

Member function pointer cast, from Derived to Base class

From Dev

Single protected member variable in base class VS Multiple private member variable in derived class

From Dev

constructor of derived class cannot be constexpr if base class contains array member

From Dev

Cast derived class to base

From Dev

Can I alias a member of the base class in derived class without increasing class memory?

From Dev

Access member of derived class from pointer of base class

From Dev

Python: Hide member of base class in derived class

From Dev

Accessing protected member in base class from a derived class

From Dev

Accessing derived class member from base class pointer

From Dev

Override the behavior of base class private member in a derived class, C++

From Dev

Member functions of a derived class

From Dev

Constructor in base and derived class

From Dev

How to access member in derived classes by a pointer of type base but pointing to the derived class

From Dev

Call a function from base class that uses the member functions of derived class

From Dev

Use derived type for member variable in derived class

From Dev

Base class private member belongs to which part of Derived class?

From Dev

constexpr base class member set by derived class

Related Related

  1. 1

    Automatic conversion from derived class to base class' member variable's type

  2. 2

    C++: How to enforce derived class to set base member variables?

  3. 3

    base pointer to derived class

  4. 4

    inheritance data member between base and derived class c++

  5. 5

    returning instance of derived class from base class member function

  6. 6

    Why "Do not access a static member that is defined in a base class from a derived class."

  7. 7

    Accessing base member functions in class derived from template class

  8. 8

    Accessing protected member in base class from a derived class

  9. 9

    Derived class cannot use member pointer to protected base class member

  10. 10

    C++: Generic base member functions with specific types in derived class

  11. 11

    Calling a member function of a derived class from the base class constructor

  12. 12

    Accessing derived class member from base class pointer

  13. 13

    Member function pointer cast, from Derived to Base class

  14. 14

    Single protected member variable in base class VS Multiple private member variable in derived class

  15. 15

    constructor of derived class cannot be constexpr if base class contains array member

  16. 16

    Cast derived class to base

  17. 17

    Can I alias a member of the base class in derived class without increasing class memory?

  18. 18

    Access member of derived class from pointer of base class

  19. 19

    Python: Hide member of base class in derived class

  20. 20

    Accessing protected member in base class from a derived class

  21. 21

    Accessing derived class member from base class pointer

  22. 22

    Override the behavior of base class private member in a derived class, C++

  23. 23

    Member functions of a derived class

  24. 24

    Constructor in base and derived class

  25. 25

    How to access member in derived classes by a pointer of type base but pointing to the derived class

  26. 26

    Call a function from base class that uses the member functions of derived class

  27. 27

    Use derived type for member variable in derived class

  28. 28

    Base class private member belongs to which part of Derived class?

  29. 29

    constexpr base class member set by derived class

HotTag

Archive