Adrian
Adrian

Reputation: 20058

What pattern to use for the following scenario?

I have the following class:

class Base {
public:
    Base(string name) {
        agg = new Aggregate(name);
    }
private:
    Aggregate* agg;
};

Now I need to extend this class:

class Derived : Base {
public:
    Derived(string name) : Base(name) {
        agg2 = new Aggregate2(name);
    }
private:
    Aggregate2* agg2;
};

What I want is when I create a Base object, Aggregate needs to be created and when I create a Derived object only Aggregate2 should be created.

Now this is not happening because Aggregate its created inside the constructor which is called when I create a Derived object and like this Aggregate and Aggregate2 would be created.

I could move the creation to a different method and call that after creating the object.
Is there any other elegant way to do what I want ?

Upvotes: 2

Views: 128

Answers (5)

I would use a constructor overload for this:

class Base {
    public:
        Base(string name) : agg(new Aggregate(name)) {}
    protected:
        Base(Aggregate* agg) : agg(agg) {}    //Base will take possession of the passed pointer.
    private:
        std::unique_ptr<Aggregate> agg;
};

class Derived : Base {
    public:
        Derived(string name) : Base(new Aggregate2(name)) {}
};

Note:
This assumes that Aggregate2 is derived from Aggregate. This assumption is based on the fact that removing ability of a base class in a derived class is at least a very strong code smell. So I concluded that both aggregates basically serve the same function, so that the second variable to hold the Aggregate2 instance is superfluous, and that Aggregate2 is a subclass of Aggregate to match behavior with relation.

Upvotes: 0

iolo
iolo

Reputation: 1090

This is something you shouldn't do. If your second class isn't supposed to have the first Aggregate member, then the right way is to make two separate classes and not to use inheritance:

class Foo1 { ... };
class Foo2 { ... };

Now if you really have a reason to use inheritance you have a few options:
- Use a base class from which both Foo1 and Foo2 will derive. The base class only contains what is common to both Foo1 and Foo2. The Aggregates you need go separately into Foo1 and Foo2. (recommended)
- Let Foo1 have a union member (if you know the whys and wherefores of unions):

union Bla { std::unique_ptr<Agg1> a1; std::unique_ptr<Agg2> a2; };  

And I should strongly emphasize that I can hardly think of an example where the second version is meaningful... Go for a separate base class!

Upvotes: 1

Ali Kazmi
Ali Kazmi

Reputation: 1458

You can have a string type data member in Base class; which can be assigned value (same as name,in constructor) and you can access it in derived also(make it protected) to initialize agg2 in Derived class.

Upvotes: 0

rajni kant
rajni kant

Reputation: 114

Try this code

class Base {
public:
    Base() { }
    Base(string name) {
        agg = new Aggregate(name);
    }
    void setName(string name) {
       agg = new Aggregate(name);
    }
private:
    Aggregate* agg;
};

class Derived : Base {
public:
    Derived(string name) {
        agg2 = new Aggregate2(name);
    }
private:
    Aggregate2* agg2;
};

Upvotes: 0

Jarod42
Jarod42

Reputation: 217085

You may use the following:

class Base {
public:
    explicit Base(string name) : agg(new Aggregate(name)) {}
protected:
    Base() = default;
private:
    std::unique_ptr<Aggregate> agg;
};

class Derived : Base {
public:
    // implicit call to Base(), you may be explicit if you want
    Derived(string name) : agg2(new Aggregate2(name)) {}
private:
    std::unique_ptr<Aggregate2> agg2;
};

Upvotes: 6

Related Questions