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;
}
posted @ 2013-08-05 23:27  曾见绝美的阳光  阅读(559)  评论(0编辑  收藏  举报