1

Class pseudo definition:

Base Virtual Class A:

class A {
public:
    virtual ~A();
    virtual void doSomething() const = 0;
};

Class B Inheriting from A:

class B : public A {
public:
    void doSomething() {} const;
}

Base Virtual Class C:

class C {
public:
    virtual ~C();
    virtual void doSomething() const = 0;
};

Class D inheriting from C:

class D : public C {
public:
    D(const &A _a = *A_Ptr(new B)) : a(_a) {}
    void doSomething() {} const;
private:
    const &A a;
}

A_Ptr is typedef of shared pointer of class A.

My problem is with declaring another class.

Lets call it class X:

class X {
public:
    X(const &A _a = *A_Ptr(new B), const &C _c = *C_Ptr(new D(a)) : a(_a), c(_c) {}
private:
    const &A a;
    const &C c;
}

X(const &A _a = *A_Ptr(new B), const &C _c = *C_Ptr(new D(a)) -this part of initialization doesn't work. What does work is

X(const &A _a = *A_Ptr(new B), const &C _c = *C_Ptr(new D)

But if I do it this way, I create two shared pointers of type class A which isn't something I would want. On the other side anything like X(const &A _a = *A_Ptr(new B), const &C _c = *C_Ptr(new D(a)) or X(const &A _a = *A_Ptr(new B), const &C _c = *C_Ptr(new D(_a)) doesn't work. Is there any known way to solve this problem?

Thanks in advance : )

Advent
  • 140
  • 15
  • 1
    By the way, `const &A _a = *A_Ptr(new B)` is a memory leak if the default argument is used! – Some programmer dude Sep 07 '18 at 08:56
  • why the members of `X` are references, when they are actually not supposed to reference something? i mean `A_Ptr(new B)` isnt something owned by someone else that `X` just wants to reference, but it seems like `X` is supposed to own it – 463035818_is_not_an_ai Sep 07 '18 at 09:00
  • @Some programmer dude: As I said it's shared pointer so once it's not longer used, memory gets freed. @ user463035818: It's matter of project, I can't make changes to level of inheritance. There is need for that. I don't run into problem when I am creating two objects of type A class using said declaration. Members are supposed to be constant references to these objects and these objects are meant to get dynamically created if there is no argument to reference existing object. – Advent Sep 07 '18 at 09:04
  • 1
    @Advent And the `shared_ptr` ceases to be used as soon as the constructor finishes, so you have a dangling reference from that point on... – Angew is no longer proud of SO Sep 07 '18 at 09:06
  • ok, have to admit I just realized that I also dont fully understand whats going on ;). Though, I still think your example here could be less verbose and still produce the same error – 463035818_is_not_an_ai Sep 07 '18 at 09:06
  • @Angew so you mean that it shouldn't work because shared_ptr is being deleted as soon as constructor ends? How should it be done then? – Advent Sep 07 '18 at 09:17
  • What for do you need these default arguments in the first place? – Michael Kenzel Sep 07 '18 at 09:25
  • There is no such thing as a "virtual class". – Lightness Races in Orbit Sep 07 '18 at 09:50

1 Answers1

2

If I understand you correctly, you need a class which either uses an external resource, or manages its own. If that's the case, you have to allow the class to do both. I believe it could work like this:

class D : public C {
public:
    D() : myA(new B), a(*myA) {}
    D(const &A _a) : a(_a) {}
    void doSomething() {} const;
private:
    std::unique_ptr<A> myA;
    const &A a;
}

This way, D can be created without arguments and will correctly manage the lifetime of the object bound to a, or it can be created with an externally-supplied A and will not create anything itself.

A similar change can be done for X:

class X {
public:
    X() : myA(new B), a(*myA), myC(new D(a)), c(*myC) {}
    X(const &A _a) : a(_a), myC(new D(a)), c(*myC) {}
    X(const &A _a, const &C _c) : a(_a), c(_c) {}
private:
    std::unique_ptr<A> myA;
    const &A a;
    std::unique_ptr<C> myC;
    const &C c;
}

Note that your original code had dangling references, since the smart pointers created as default arguments go out of scope when the constructor run finishes. That's why they have to be stored somewhere in the class, as the solution above does.

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455