在c ++入门15.8中,当作者谈到“处理类和继承”时,他说:
'C ++中的常用技术是定义所谓的封面或句柄类。 handle类存储和管理指向基类的指针。指针指向的对象类型将有所不同;它可以指向基础或派生类型的对象。用户通过句柄访问继承层次结构的操作。因为句柄使用其指针来执行这些操作,所以虚拟成员的行为在运行时会有所不同,具体取决于句柄实际绑定到的对象的类型。因此,句柄的用户获得了动态行为,但他们自己不必担心管理指针。
以上听起来非常像是指向我的智能指针。但是,这个'句柄'的用法略有不同。
Handle h(Derived()); // noticed a derived object, not a pointer is used to initialize the handle!
h->func();
后面的句柄实现(如下所示)证明了作者对句柄的评论:'我们希望我们句柄的用户创建自己的对象,他们可以附加句柄。 句柄将分配适当类型的新对象,并将用户的对象复制到新分配的对象。这样句柄类将拥有对象,并且可以保证在附加到对象的最后一个句柄消失之前不会删除该对象。'
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
};
我的问题是:这真的是c ++或OO中句柄的典型含义吗?我认为句柄可以只是一个基本类型的智能指针,它在内部保持use-count,或者更普遍的是一些magic int类型,系统知道它指向什么以及如何处理它。为什么这里处理需要将用户对象的副本复制到自身,然后根据副本使用count?
有人帮忙吗?
谢谢,
答案 0 :(得分:4)
现代C ++中惯用的等价物是:
std::shared_ptr<Base> h{std::make_shared<Derived>()};
通常,“句柄”意味着某种形式的类型擦除,因此处理句柄的代码不需要知道如何实现功能的细节。
您显示的代码使用clone
复制对象的原因正是为了执行类型擦除;在调用clone
方法时,将清除Derived
对象的实际类型的知识。在实现质量方面,代码是非线程安全的,这与传统C ++无关,但是现代C ++存在问题,它具有线程感知内存模型。它也显然不是例外安全的;将异常安全性委托给标准库类(如shared_ptr
)要好得多。最后,Base
类缺少虚拟析构函数。