我有以下课程:
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
对象时调用的构造函数内创建的,并且会创建Aggregate
和Aggregate2
。
我可以将创建移动到另一个方法,并在创建对象后调用它 有没有其他优雅的方式来做我想要的?
答案 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
实例的第二个变量是多余的,Aggregate2
是Aggregate
的子类,以匹配行为与关系