已经涵盖了指针(及其陷阱)的使用,所以我将向您展示如何在没有动态内存分配的情况下使用多态性,这可能证明我是一个即使考虑它的异端。
首先,让我们看看你的原始代码,修补后编译:
void foo(bool const cond) {
Base* b = 0;
if (cond) { b = new Derived1(); }
else { b = new Derived2(); }
b->func1();
delete b; // do not forget to release acquired memory
}
假设你有一个virtual
析构函数,它工作正常Base
。
程序员进化的下一个合乎逻辑的步骤是使用智能指针来避免编写delete
(delete
仅由初学者和专家库编写者使用):
void foo(bool const cond) {
std::unique_ptr<Base> b;
if (cond) { b.reset(new Derived1()); }
else { b.reset(new Derived2()); }
b->func1();
}
当然,它仍然需要一个virtual
析构函数Base
。
让我们意识到这个函数做了两件事:
我们可以将其分解,例如通过提取构建工作:
std::unique_ptr<Base> build(bool const cond) {
if (cond) { return { new Derived1() }; }
return { new Derived2() };
}
void foo(bool const cond) {
std::unique_ptr<Base> b = build(cond);
b->func1();
}
这是大多数人所做的。
我声称还有另一种可能性,我们可以隔离实际工作,而不是隔离构建:
void dowork(Base& b) { b.func1(); /* and perhaps other things */ }
void foo(bool const cond) {
std::unique_ptr<Base> b(cond ? new Derived1() : new Derived2());
work(*b);
}
我们实际上可以更进一步:
void foo(bool const cond) {
if (cond) {
Derived1 d;
work(d);
} else {
Derived2 d;
work(d);
}
}
多态性不需要动态内存分配。
你知道最后一个例子有什么好玩的:
- 没有 C++11 移动语义,它工作得很好
- 它不需要有
virtual
析构函数Base