C++一些特殊的类的设计
一、设计一个只能在栈上分配空间的类
重写类的opeator new 操作,并声明为private,一个大概的代码如下:
class StackOnly
{public:
StackOnly(){/*constructor*/}
~StackOnly(){/*destructor*/};
private:
void *operator new(size_t size);};int main()
{StackOnly s; //正确用法,自动变量在栈上分配内存
StackOnly * ps = new StackOnly(); //错误,全局new操作符无法调用operator new操作分配堆上内存return 0;
}
这是一个面试题,考察的是反应速度和对知识掌握的熟悉程度,不过这个题目也有些让人迷惑,很多人想得到要改写new operator,但是却会陷入new opeator的底层怎么实现这个死循环中,误认为这个类的使用方法跟其他类一样,只是底层获取内存的方式变了,但是实际上只是不准客户使用new 这种声明方式。
二、设计一个只能在堆上分配内存的类
这题和设计一个只能在栈上分配空间的类是一样的思路,只能在堆上分配空间意味着只能以A * pa = new A(…);这种形式来获取内存,而不能通过A a;这种形式来获取。它的思路是这样的:将析构函数声明为protected 或者private ,这样的话,如果用A a ;这种内存获取方式,会导致析构函数调用出错。于是,相应的代码如下:
class HeapOnly
{public:
HeapOnly(){/*constructor*/};
void destroy(){/*do things ought to be done by destructor*/}private:
~HeapOnly(){/*destructor*/}
};int main()
{HeapOnly h ; //错误用法,无法调用析构函数
HeapOnly *ph = new HeapOnly(); //正确用法ph->destroy(); //因为无法调用析构函数,所以要自行释放内存
}
三、设计一个不能被继承的类
很容易想到的一个思路就是将此类的构造函数私有化,那么子类就无法调用父类的构造函数了,自然无法构建父类部分,但是这样的话就不能够正常使用这个类了,因为无法正常地构造函数,只能按照如下的方法来实现一个类:
class NoInheritance
{public:
static NoInheritance * getInstance(){return new NoInheritance();}static void destroy(NoInheritance * pN){delete pN; };private:
NoInheritance();~NoInheritance();};int main()
{NoInheritance *ni = NoInheritance.getInstance();NoInheritance.destroy(ni);return 0;
}
以上的确是个可行的方案,可惜就是用起来不太方便,利用友元的概念可以实现一个很好的不能被继承的类,如下:
class NoHeritance
{private:
NoHeritance();~NoHeritance();friend class CBase;};class CBase:virtual public NoHeritance{public:
CBase();~CBase();private:
//members
}
虚基类最终只能由最终子类构造,CBase作为虚基类NoHeritance的友元,是可以调用其private函数的,但是友元性质不能被继承,如果Child想要继承CBase ,需要调用NoHeritance 的构造函数,这是行不通的,于是我们就构造了一个不能被继承的类。(参考:http://blog.csdn.net/doudou745/article/details/7277164)
四、设计一个只能有一个实例的类
这是典型的设计模式,单例模式。如果不考虑多线程安全,大概的代码如下:
#include<iostream>using namespace std;class Singleton
{public:
static Singleton * GetInstance()//通过静态公有函数获得该类的实例对象{if(m_pInstance==NULL)
m_pInstance=new Singleton();
return m_pInstance;
}private:
Singleton(){}//构造函数私有化的目的是为了防止从别处实例化该类对象
static Singleton * m_pInstance;
class Garbo//删除Singleton实例的对象{public:
~Garbo(){if(Singleton::m_pInstance)
{delete Singleton::m_pInstance;
}}};static Garbo gb;//在程序结束时,系统会调用它的析构函数};Singleton * Singleton::m_pInstance=NULL;//初始化静态数据成员
int main()
{Singleton *sl=Singleton::GetInstance();return 0;
}