2

I have an abstract base class Base that contains a pointer to another abstract base class BaseDataClass. I have derived classes for both classes, I'll call them Derived and DerivedDataClass. The Base does not know that DerivedDataClass exists, and in any case, I intend to later have multiple combinations of Base and BaseDataClass subclasses . In the derived class, I want the pointer to be set to an instance of the derived data class, but I don't want to accidentally be able to assign the pointer later on so I made it const. This obviously keeps me from assigning the pointer using new in the derived class's constructor. Is there a neat way to accomplish this while keeping the pointer const?

class BaseDataClass
{
public:
    BaseDataClass(){}
    //some pure virtual methods
};

class Base
{
public:
    Base(){}
    //some pure virtual methods

protected:
    BaseDataClass * const data; //compiler complains if this isn't set

};



//// elsewhere
class DerivedDataClass : public BaseDataClass
{
public:
    DerivedDataClass(){}
};


class Derived : public Base
{
public:
    Derived(){
        data = new DerivedDataClass(); //also does not compile obviously
    }

};
Cobalt
  • 938
  • 9
  • 21

1 Answers1

1

Const objects cannot be assigned to. You must set the value of the const member upon initialisation. If you initialise to null, then it will always be null. So, don't initialise to null. In order to let the derived class choose what to initialise it to, use a constructor argument:

Base::Base(BaseDataClass *);

You can use that argument to initialise the member.


That said:

  • If you use new in constructor, you should make sure that you eventually delete it or else you will leak memory.
  • You cannot delete through the pointer to base, because the destructor of the base is not virtual.
  • Bare owning pointers are a bad design. You should use smart pointers instead.
eerorika
  • 232,697
  • 12
  • 197
  • 326
  • If I don't initialize to null, it does not compile because the base class constructor must explicitly initialize it. I cannot initialize it as you have shown because the base class does not know about the derived data class. – Cobalt Jul 16 '19 at 18:33
  • @Cobalt Good point. See edit. – eerorika Jul 16 '19 at 18:37
  • Nice, that works. Just to be clear - my actual classes have virtual destructors, I just didn't show them due to laziness. In the destructor for `Base`, the pointer to `BaseDataClass` is deleted. My constructor looks like this, which I presume is what you meant: `Derived() : Base(new DerivedDataClass()) { }`. Will this still leak or am I good? – Cobalt Jul 16 '19 at 18:50
  • @Cobalt That seems good as far initialisation of const pointer is concerned. But to avoid memory leak, you must delete the pointer before it is destroyed. – eerorika Jul 16 '19 at 18:51