OOP13:SmartPointer
第13章 SmartPointer
13.1 设计目标
- 记录当前对象被引用了多少次 reference count
- 类UCObject用来记录次数,use-counted object
- 类UCPointer用来指向UCObject
- 智能指针是通过一个类定义的
- 使用模板实现
- 重载操作符->和*****
13.2 设计类和接口
- UCObject:实现reference count
- UCPointer:是一个类模板,支持指向任意一个类型的UCObject
- String Rep:字符串表示的细节,是可共享的
- String:再封装一层,提供给用户
13.3 实现细节
UCObject
class UCObject {
private:
int m_refCount;
public:
UCObject() : m_refCount(0) { }
UCObject(const UCObject&) : m_refCount(0) { }
// 析构函数需要是virtual的,因为使用的时候,我们通常会使用父类指针指向子类,但是析构的时候要正确调用子类的析构函数
virtual ~UCObject() {
assert(m_refCount == 0);
};
// 接口不需要virtual, 因为所有子类的这些操作都是一样的
void incr() {
m_refCount++;
}
void decr() {
m_refCount -= 1;
if (m_refCount == 0)
delete this;
}
int references() {
return m_refCount;
}
};UCPointer
template <class T>
class UCPointer {
private:
T* m_pObj;
// 下列两个函数表明: T继承自UCObject, 否则调用incr(),decr()时编译器会报错
// 因为UCPointer要像指针一样使用, 因此将这两个函数放入private中
void increment() {
if (m_pObj) m_pObj->incr();
}
void decrement() {
if (m_pObj) m_pObj->decr();
}
public:
UCPointer(T* r = 0): m_pObj(r) {
increment();
}
~UCPointer() {
decrement();
};
UCPointer(const UCPointer<T> & p){
m_pObj = p.m_pObj;
increment();
}
UCPointer& operator=(const UCPointer<T> &){
if (m_pObj != p.m_Obj){
decrement();
m_pObj = p.m_pObj;
increment();
}
return *this;
}
T* operator->() const{
return m_pObj;
}
T& operator*() const {
return *m_pObj;
};
};使用实例:假设Shape继承自UCObject
Ellipse elly(200F, 300F);
UCPointer<Shape> p(&elly);
p->render(); // calls Ellipse::render() on elly!String
- StringReq继承自UCObject
- String提供用户使用的
class String {
public:
String(const char *);
~String();
String(const String&);
String& operator=(const String&);
int operator==(const String&) const;
String operator+(const String&) const;
int length() const;
operator const char*() const;
private:
UCPointer<StringRep> m_rep;
};
String::String(const char *s) : m_rep(0) {
m_rep = new StringRep(s);
}
String::~String() {}
// Again, note constructor for rep in list.
String::String(const String& s) : m_rep(s.m_rep) {}
String& String::operator=(const String& s) {
m_rep = s.m_rep; // let smart pointer do work!
return *this;
}
int String::operator==(const String& s) const {
// overloaded -> forwards to StringRep
return m_rep->equal(*s.m_rep); // smart ptr *
}
int String::length() const {
return m_rep->length();
}StringRep
class StringRep : public UCObject {
public:
StringRep(const char *);
~StringRep();
StringRep(const StringRep&);
int length() const{ return strlen(m_pChars); }
int equal(const StringRep&) const;
private:
char *m_pChars;
// reference semantics -- no assignment op!
void operator=(const StringRep&) { }
};
StringRep::StringRep(const char *s) {
if (s) {
int len = strlen(s) + 1;
m_pChars = new char[len];
strcpy(m_pChars , s);
} else {
m_pChars = new char[1];
*m_pChars = '\0';
}
}
StringRep::~StringRep() {
delete [] m_pChars ;
}
StringRep::StringRep(const StringRep& sr) {
int len = sr.length();
m_pChars = new char[len + 1];
strcpy(m_pChars , sr.m_pChars );
}
int StringRep::equal(const StringRep& sp) const {
return (strcmp(m_pChars, sp.m_pChars) == 0);
}
13.4 细节
- UCPointer维护了reference counts
- UCObject隐藏了count的细节,使得String非常干净
- StringReq只处理字符串的存储和操作
- UCObject和UCPointer是可重用的
- 当UCPointer的对象有环时,对象不会被delete
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 华风夏韵!
评论