C++ 句柄类
c++ 中多态只有通过对象的引用或指针调用时才生效,通过普通对象调用成员函数不支持多态。比如以下容器和多态的例子:
#include <iostream>
using namespace std;
class Base {
public:
virtual void name() const { cout << "Base" << endl; }
};
class BaseA : public Base {
public:
virtual void name() const { cout << "Base A" << endl; }
};
int main() {
// 对象直接调用,多态不生效
vector<Base> bases;
bases.push_back(Base());
bases.push_back(BaseA());
for (vector<Base>::const_iterator it = bases.begin(); it != bases.end(); it ++) {
it->name();
}
// 指针调用,多态生效
vector<Base*> basePtrs;
basePtrs.push_back(new Base());
basePtrs.push_back(new BaseA());
for (vector<Base*>::iterator it = basePtrs.begin(); it != basePtrs.end(); it ++) {
(*it)->name();
}
return 0;
}
输出:
Base
Base
Base
Base A
所以要让容器中的元素支持多态,必须通过保存对象指针。但这样做面临指针的管理,用户要保证容器存在时,存放的指针对象有效。
c++ 提供了对这类指针的封装称为句柄类。句柄类中包含基类指针类型的成员变量,以及对该指针的计数管理。当容器调用句柄类对象时,对象的指针成员支持多态。用户无须操心指针的管理。
句柄类的实现,类似于共享指针,实现共享指针的共享引用计数使用的是 int 指针,而不是额外的计数存储类。
#include <iostream>
using namespace std;
class Base {
public:
virtual void name() const { cout << "Base" << endl; }
// clone 函数
virtual Base* clone() const { return new Base(*this); }
};
class BaseA : public Base {
public:
virtual void name() const { cout << "Base A" << endl; }
virtual BaseA* clone() const { return new BaseA(*this); }
};
class BaseHandle {
public:
// 默认构造函数
BaseHandle() : p(0), use(new int(1)) {}
// 从 Base 引用初始化的构造函数
BaseHandle(const Base &b) : p(b.clone()), use(new int(1)) {}
// 复制构造函数
BaseHandle(const BaseHandle &b) : p(b.p), use(b.use) { ++ *use; }
// 赋值操作
BaseHandle& operator=(const BaseHandle &rhs) {
++ *rhs.use;
decr();
p = rhs.p;
use = rhs.use;
return *this;
}
const Base* operator->() const {
if (p) return p;
else throw logic_error("unbound pointer");
}
const Base& operator*() const {
if (p) return *p;
else throw logic_error("unbound pointer");
}
~BaseHandle() { decr(); }
private:
Base *p;
// 首先智能指针,通过定义为指针共享计数(另一种方式是新增共享指针计数类)
int *use;
void decr() {
if (-- *use == 0) {
delete p; delete use;
}
}
};
int main() {
// 普通对象函数调用,多态不生效
vector<Base> bases;
bases.push_back(Base());
bases.push_back(BaseA());
for (vector<Base>::const_iterator it = bases.begin(); it != bases.end(); it ++) {
it->name();
}
// 指针类型调用,多态生效
vector<Base*> basePtrs;
basePtrs.push_back(new Base());
basePtrs.push_back(new BaseA());
for (vector<Base*>::iterator it = basePtrs.begin(); it != basePtrs.end(); it ++) {
(*it)->name();
}
// 句柄类型调用,多态生效,且句柄类自动管理指针对象(智能指针)
vector<BaseHandle> handles;
handles.push_back(BaseHandle(Base()));
handles.push_back(BaseHandle(BaseA()));
for (vector<BaseHandle>::iterator it = handles.begin(); it != handles.end(); it ++) {
(*it)->name();
}
return 0;
}
输出:
Base
Base
Base
Base A
Base
Base A
句柄类用于配合容器元素支持多态,同时又无须用户自行管理指针。
0 条评论