一,题目:如下为类型为CMyString的声明,请为该类型添加赋值运算符函数
class CMyString
{
public:
CMyString(char* pData = NULL);
CMyString(const CmyString& str);
~CMyString(void);
private:
char * m_pData;
}
类的默认函数有四个分别是构造函数,析构函数,拷贝构造函数和赋值运算符重载函数。
拷贝构造函数的形参一定要是引用,防止递归调用拷贝构造形参对象的情况。
赋值运算符的重载的形参为const,目的一是防止实参被修改,二是接收隐式生成的临时量。
设计步骤:首先要进行自赋值的判断,然后释放旧的资源,最后赋新资源。
根据以上特点我们实现一个赋值运算符的重载函数如下:
CMyString& CMyString::operator=(const CMyString& rhs)//返回一个引用,为了允许连续赋值常量参数类
//型声明为常量引用,避免形参传实参时调用拷贝构造函数,赋值不改变传入实例的状态,所以传入的引用应加上
//const关键字。
{
if(tish == &rhs)//判断自赋值,考虑到如果当前实例和传入实例是同一个,那么在释放实例自身的内存时
//会产生严重的问题,即:当*this和传入的参数是同一个实例时,那么一旦释放了自身的内存,传入的参数内存也
//同时被释放了,因此就找不到需要赋值的内容了。
{
return *this;
}
delete[] m_pData;//防止出现内存泄漏
m_pData = NULL;
m_pData = new char[strlen(rhs.m_pData)+1)]();
memcpy(m_pData,rhs.m_pData,strlen(rhs.m_pData)+1);
return *this;
}
考虑到一种情况,由于我们是先delete了实例m_pData的内存,此时如果我们new的时候内存不足,在赋值运算符内部出现一个异常,CMyString的实例就会被修改,因此我们可以先申请内存后释放旧内存;或者创建临时实例,再交换临时实例和原来的实例。临时实例的生命周期到了之后系统会自动将其析构,这样子保证了程序的异常安全性。
二,题目:设计一个类,我们只能生成该类的一个实例
典型的单例模式,实现单例模式需要以下几点:1,把生成对象的接口屏蔽起来,包括构造函数和拷贝构造函数,将其写在类的私有之下,由于只能生成一个对象,所以拷贝构造函数根本用不上,所以我们不用实现,只要把声明写在私有之下就可以了。然后我们在类中提供一个接口来生成唯一的对象
class Singleton//普通模式下的单例模式
{
public:
static Singleton* getInstance()
{
return &single;
}
//static Singleton& getInstance()
//{
// return single;
//}
private:
Singleton(){}
Singleton(const Singleton&);
static Singleton single;
};
Singleton Singleton::single;
class Singeton()//双重锁机制下的单例模式
{
public:
static Singleton* getInstance()
{
if(psing == NULL)
{
//lock()
if(psing == NULL)
{
psing = new Singleton();
}
//unlock();
}
return psing;
}
private:
Singleton(){}
Singleton(const Singleton&);
static Singleton* psing;
};
Singleton* Singleton::psing = NULL;