【问题标题】:Should objects with virtual member functions always be instantiated on the heap?具有虚拟成员函数的对象是否应该始终在堆上实例化?
【发布时间】:2022-11-25 19:00:16
【问题描述】:
据我所知,具有虚拟成员函数的具体类型D的对象应该通过指向它们(可能是抽象的)基类B的指针来使用。否则,将功能虚拟化是没有意义的。有三个重要的“指针选项”:
- 指向
B 的原始指针指向堆栈上D 类型的对象。
- 指向
B 的原始指针指向堆上D 类型的对象。
- 拥有指向
B 的智能指针(唯一或共享)指向堆上D 类型的对象。
通常不鼓励选项 2 而支持选项 3。在面向对象的编程中,我们通常喜欢通过组合从简单的对象中组装出复杂的对象。在这种情况下,选项 3 提供了传达所有权和管理对象生命周期的额外优势,例如具有唯一指针成员的类的对象负责指向的对象,并且不会超过后者。
因此,总是在堆上实例化具有虚拟成员函数的类的对象并让所有工厂函数返回智能指针是一种好习惯吗?
【问题讨论】:
标签:
c++
pointers
polymorphism
heap-memory
virtual-functions
【解决方案1】:
“否则,将这些功能虚拟化是没有意义的。” - 是的,这里有一个例子:
// say this is a library interface
struct Base
{
virtual hello() = 0;
}
// external to the library
class Derived
{
hello() override { std::cout << "hello from Derived" << std::endl; }
}
// say this is a library function,
// which does not need to know about Derived
void sayHelloNTimes(Base& b, size_t n)
{
for (size_t i = 0; i < n; ++i) {
b.hello();
}
}
int main() {
Derived d;
sayHelloNTimes(d, 3);
}
通常,使用virtual 的原因只是为了将接口与实现分离。
至于关于智能指针的问题:当你想确保特定的所有权时,你从 create() 函数返回它们(并使 ctor 等私有)。一个例子是当类保留所创建元素的(句柄)副本时。另一个是当您的公共库函数需要做同样的事情时。通常情况下,除非万不得已,否则不要限制它。