在 C++ 中处理类?

use*_*625 4 c++ inheritance

在C++ Primer 15.8中,当作者谈到“处理类和继承”时,他说:

C++ 中的一种常见技术是定义所谓的覆盖类或句柄类。句柄类存储并管理指向基类的指针。该指针指向的对象的类型会有所不同;它可以指向基类型对象或派生类型对象。用户通过句柄访问继承层次结构的操作。由于句柄使用其指针来执行这些操作,因此虚拟成员的行为在运行时将根据句柄实际绑定到的对象类型而变化。因此,句柄的用户可以获得动态行为,但自己不必担心管理指针。

上面的内容对我来说听起来非常像一个智能指针。然而,这个“句柄”的用法有点不同。

Handle h(Derived()); // noticed a derived object, not a pointer is used to initialize the handle!
h->func();
Run Code Online (Sandbox Code Playgroud)

句柄的后一个实现(如下所示)证明了作者对句柄的评论:

我们希望我们的句柄的用户创建他们自己的对象,他们可以将句柄附加到该对象上。该句柄将分配一个适当类型的新对象,并将用户的对象复制到该新分配的对象中。这样,句柄类将拥有该对象,并且可以保证在附加到该对象的最后一个句柄消失之前该对象不会被删除。

代码:

public:
    Base(){}
    virtual int func(std::size_t n) const {}
    virtual Base* clone() const { return new Base(*this); }
};

class Derived : public Base {
public:
    Derived():Base(){}
    int func(std::size_t) const; // redefine
    Derived* clone() const { return new Derived(*this); }
};

class Handle {
public:
    Handle(const Base &b):p(b.clone()), use(new std::size_t(1)) { }
private:
    Base *p;
    std::size_t *use; // pointer to shared use count
};
Run Code Online (Sandbox Code Playgroud)

我的问题是:这真的是 C++ 或 OO 中句柄的典型含义吗?我认为句柄可以只是一个基本类型的智能指针,在内部保留使用计数,或者更一般地说,是一些魔法 int 类型,系统知道它指向什么以及如何处理它。为什么这里的句柄需要将用户对象复制到自身,然后根据副本进行使用计数?

eca*_*mur 5

现代 C++ 中的惯用用法是:

std::shared_ptr<Base> h{std::make_shared<Derived>()};
Run Code Online (Sandbox Code Playgroud)

一般来说,“句柄”意味着某种形式的类型擦除,因此处理句柄的代码不需要知道功能如何实现的细节。

您所显示的代码用于复制对象的原因clone正是为了执行类型擦除;当调用该clone方法时,对象实际类型的知识Derived将被删除。就实现质量而言,代码是非线程安全的,这与传统 C++ 无关,但对于现代 C++ 来说是一个问题,现代 C++ 确实具有线程感知内存模型。它也不是明显的异常安全的;将异常安全委托给标准库类(例如shared_ptr. 最后,该类Base缺少虚拟析构函数。