简体   繁体   中英

using smart pointers in a derived class constructor

The question, at the outset: (preface: new to c++ oop programming)

How do I construct a derived class, Widget , such that I have a vector of (shared?) pointers in terms the base class, where the original objects (such that they are still of the derived class) can be accessed upon casting and dereferencing the pointers?



Say I have a base class:

class Component {
public: 
    int a; 
    int b;
    virtual void rtti(){}; // for run time type information.
    explicit Component(int a, int b) { this->a = a; this->b = b;}
}

And two derived classes,

class AComponent:public Component{
public:
    using Component::Component;
    AComponent(int a, int b) : Component(int a, int b){}
}    

class BComponent:public Component{
public:
    using Component::Component;
    BComponent(int a, int b) : Component(int a, int b){}
}

Further, I have a Multi-Component (still generic here):

typedef shared_ptr<AComponent> AComponentPtr;
typedef shared_ptr<BComponent> BComponentPtr;
class MultiComponent{
public:
    vector<AComponentPtr> A_components;
    vector<BComponentPtr> B_components;

    explicit MultiComponent(vector<AComponentPtr> As, vector<BComponentPtr> Bs){
        this->A_components = As;
        this->B_components = Bs;
    }
}

Finally, I have a specific use case of this component hierarchy:

class WidgetComponentA:public AComponent{...}
class WidgetComponentB:public BComponent{...}

class Widget:public MultiComponent{
public:
    using MultiComponent::MultiComponent;

    Widget(WidgetComponentA a, WidgetComponentB b, WidgetComponentB c)
        : MultiComponent(???){
    }
}

Currently, I have the MultiComponent class constructor within Widget set up as follows:

class Widget:public MultiComponent{
public:
    using MultiComponent::MultiComponent;

    Widget(WidgetComponentA a, WidgetComponentB b, WidgetComponentB c)
        : MultiComponent({(AComponentPtr)&a},{(BComponentPtr)&b, (BComponentPtr)&c}){}
}

Because this yields no errors on compilation.

Then, I construct the widget in my main method like so:

main(){

    WidgetComponentA a = WidgetComponentA(1,2);
    WidgetComponentB b = WidgetComponentB(3,4);
    WidgetComponentB c = WidgetComponentB(5,6);

    // now, the widget: 

    Widget widget = Widget(a,b,c);

    // however, the pointers within the widget 
    // do not access valid addresses in memory. 

return 0;}

The shared pointers within the Widget widget object do not reference any valid locations in memory, and fail with,

Attempt to take address of value not located in memory.



Ultimately, what I am trying to do is have Widget just hold on to the list of components of various derived types in the form of the base class shared pointers.

Then, I run generic, template functions on the class, and only cast the pointers to the widget-specific derived class pointers in functions specific to widgets.

I am using shared pointers to be safe, because I ran into the memory leak warnings...but if there is a simpler solution...

As I suggested in the comments, perhaps a polymorphic approach would be easier...

class MultiComponent{
  public:
    typedef std::vector<std::shared_ptr<Component>> components_vec;
    components_vec components;

    MultiComponent(components_vec& cv){
        components = cv;
    }
}

class Widget: public MultiComponent {
  public:

    Widget(MultiComponent::components_vec& cv)
        : MultiComponent(cv){}
}

You can cast pointers to descendants of Component to Component* 's and then store them together.

Then, perhaps define a virtual void Component::display() = 0 to force the inheritors to define some sort of behaviour to your needs.

Perhaps I misunderstand what you ask but if you want to deal with objects of shared ownership then you have to make them such:

main()
{
    auto a = std::make_shared<WidgetComponentA>(1,2);
    auto b = std::make_shared<WidgetComponentB>(3,4);
    auto c = std::make_shared<WidgetComponentB>(5,6);

    // now, pass the shared stuff to widget: 

    Widget widget = Widget(a,b,c); // make sure that Widget has
                                   // such constructor that accepts
                                   // the shared pointers

    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM