![](/img/trans.png)
[英]Can an abstract class be member of other concrete class as composition relationship ? c++
[英]C++ Composition with abstract class
假设我有一个抽象类,创建和复制是昂贵的:
class AbstractBase {
public:
AbstractBase() {
for (int i = 0; i < 50000000; ++i) {
values.push_back(i);
}
}
virtual void doThing() = 0;
private:
vector<int> values;
};
它有两个子类FirstDerived
:
class FirstDerived : public AbstractBase {
public:
void doThing() {
std::cout << "I did the thing in FirstDerived!\n";
}
};
和SecondDerived
:
class SecondDerived : public AbstractBase {
public:
void doThing() {
std::cout << "I did the thing in SecondDerived!\n";
}
};
此外,我想创建一个使用组合(不是聚合)来利用FirstDerived
或SecondDerived
的类。 这意味着我希望ComposedOfAbstractBase
拥有传入的临时值。如果我在这个类中没有使用抽象类,则看起来像:(在C ++ 11中)
class ComposedOfWhicheverDerived {
public:
ComposedOfWhicheverDerived(AbstractBase abstract_base) : abstract_base(std::move(abstract_base)) {;}
private:
AbstractBase abstract_base;
};
但是,这不适用于抽象类,因为我不能创建AbstractBase
的实例,即使我小心不传入临时的AbstractBase
,如下所示:
ComposedOfWhicheverDerived a(FirstDerived());
对于编译器来说,这与以下一样糟糕:
ComposedOfWhicheverDerived b(AbstractBase());
因为我在类声明中仍然有一个AbstractBase
实例。
我想出的下一个解决方案是:
class ComposedOfAbstractBase {
public:
ComposedOfAbstractBase(AbstractBase&& abstract_base) : some_derived_instance(abstract_base) {;}
private:
AbstractBase& some_derived_instance;
};
这完美地工作(即使我不完全理解它)! 这两个实例都是有效的并且按预期工作:
ComposedOfAbstractBase a(FirstDerived());
ComposedOfAbstractBase b(SecondDerived());
它不会创建传递任何AbstractBase
临时文件的副本,并且允许存储对AbstractBase
的引用。 虽然充其量只是对rvalue引用的引用似乎不清楚:它没有表明ComposedOfAbstractBase
拥有传入的临时值。除此之外,事实证明这个解决方案似乎是次优的。 为了表明这一点,我创建了这个类:
class ComposedOfFirstDerived {
public:
ComposedOfFirstDerived(FirstDerived first_derived) : first_derived(std::move(first_derived)) {;}
private:
FirstDerived first_derived;
};
哪个只能接受FirstDerived
,所以我们可以应用std::move
来卸载临时的所有权。 我可以像这样制作一个实例:
ComposedOfFirstDerived c(FirstDerived());
有趣的是,这个类的创建速度始终比ComposedOfAbstractClass
快10%。
有谁知道这里发生了什么? 为什么ComposedOfFirstDerived
创建速度比ComposedOfAbstractBase
快得多? 是否有更好的方法来使用抽象类进行组合,还是我坚持使用次优解?
对不起,如果这是一个问题。 我感谢任何花时间阅读并给出真实答案的人,因为我无法忍受!
ComposedOfAbstractBase
不是解决方案。 你拿着悬挂的参考。
由于AbstractBase
,顾名思义,抽象 - 你不能按值保持一个。 您只能通过引用或指针来保存一个。 由于引用不能拥有该对象,因此会留下指针。 拥有指针的现代方法是使用unique_ptr
:
class ComposedOfAbstractBasePtr {
public:
ComposedOfAbstractBasePtr(std::unique_ptr<AbstractBase> p)
: some_derived_instance(std::move(p))
{ }
private:
std::unique_ptr<AbstractBase> some_derived_instance;
};
请注意,您的AbstractBase
没有虚拟析构函数。 你应该解决这个问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.