用于以下场景的模式是什么?

时间:2014-12-22 08:56:06

标签: c++ design-patterns

我有以下课程:

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

现在我需要扩展这个类:

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

我想要的是当我创建Base对象时,需要创建Aggregate,当我创建Derived对象时,只应创建Aggregate2

现在没有发生这种情况,因为Aggregate它是在我创建Derived对象时调用的构造函数内创建的,并且会创建AggregateAggregate2

我可以将创建移动到另一个方法,并在创建对象后调用它 有没有其他优雅的方式来做我想要的?

5 个答案:

答案 0 :(得分:6)

您可以使用以下内容:

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;
};

答案 1 :(得分:1)

这是你不应该做的事情。如果你的第二个类不应该有第一个Aggregate成员,那么正确的方法是创建两个单独的类,来使用继承:

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

现在,如果你真的有理由使用继承,你有几个选择:
- 使用Foo1和Foo2将从中派生的基类。基类只包含Foo1和Foo2共有的内容。您需要的聚合分别进入Foo1和Foo2。 (的推荐
- 让Foo1有一个工会成员(如果你知道工会的原因和原因):

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

我应该强烈强调,我很难想到第二个版本有意义的例子......去一个单独的基类!

答案 2 :(得分:0)

试试此代码

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;
};

答案 3 :(得分:0)

您可以在Base类中拥有字符串类型数据成员;可以赋值(与构造函数中的名称相同),您也可以在派生中访问它(使其受保护)以初始化派生类中的agg2。

答案 4 :(得分:0)

我会使用构造函数重载:

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)) {}
};

注意:
这假定Aggregate2源自Aggregate。该假设基于以下事实:在派生类中删除基类的能力至少是非常强的代码气味。所以我得出结论,两个聚合基本上都提供相同的函数,因此保存Aggregate2实例的第二个变量是多余的,Aggregate2Aggregate的子类,以匹配行为与关系