用于以下方案的模式

What pattern to use for the following scenario?

本文关键字:模式 方案 用于      更新时间:2023-10-16

我有以下类:

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将被创建。

我可以将创建移动到其他方法,并在创建对象后调用该方法。
还有其他优雅的方式来做我想做的事吗?

您可以使用

以下内容:

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

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

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

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

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

应该强烈强调,我几乎想不出第二个版本有意义的例子......去一个单独的基类!

试试这段代码

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

你可以在基类中有一个字符串类型的数据成员;它可以被赋值(与 name,在构造函数中相同(,你也可以在 Derived 中访问它(使其受到保护(以初始化 Derived 类中的 agg2。

我会为此使用构造函数重载:

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实例的第二个变量是多余的,并且Aggregate2是将行为与关系匹配的Aggregate子类。