一、设计一个只能在栈上分配空间的类

重写类的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;

}

C++一些特殊的类的设计的更多相关文章

  1. Unity3D 游戏开发构架篇 ——角色类的设计与持久化

    在游戏开发中,游戏角色占了很大的篇幅,可以说游戏中所有的内容都是由主角所带动.这里就介绍一下角色类的设计和持久化. 一.角色类应用场景和设计思想 游戏中的角色类型不一而足,有不同的技能,有不同的属性等 ...

  2. “乐”动人心--2017年10款最佳音乐类APP设计盘点

    在上下班的路上,听几首自己喜欢的音乐来打发无聊的等公交车和地铁的时间是现代年轻人的常态.音乐作为最能鼓动人心的"语言",也成为了人们在互联网生活里占比例最高的消费活动之一,一款好看 ...

  3. Java SE 之 数据库操作工具类(DBUtil)设计

    JDBC创建数据库基本连接 //1.加载驱动程序 Class.forName(driveName); //2.获得数据库连接 Connection connection = DriverManager ...

  4. 学员会诊之02:SVN协作以及Page类的设计

    三层架构的学生管理系统是我们第一个稍微大型的项目:分层.一个解决方案多个Project,所以值得我们停下来好好审查审查. 1.测试SVN服务器地址 我们的作业要求学员创建自己的SVN服务器,并且将代码 ...

  5. Date类为什么设计为可变的,而不是像String一样?

    首先,不得不承认,这确实是类库设计的一个错误,所以"为什么"进行了这个错误设计并没有意义.但没有事物一诞生就是完美的,我们的Java只是反应的慢了一点,再慢了一点. 更何况,Dat ...

  6. Python面向对象 --- 类的设计和常见的内置方法

    面向对象:一种基于面向过程的新的编程思想.也就是说面向对象是将功能等通过对象来实现,将功能封装进对象之中,让对象去实现具体的细节:这种思想是将数据作为第一位,而方法或者说是算法作为其次,这是对数据一种 ...

  7. Java实验项目三——编程实现Person类,学生类的设计及其继承关系

    Program: 编程实现Person类,学生类的设计及其继承关系 代码如下: 定义抽象类Person 1 /* 2 * Description:建立抽象类 3 * 4 * Written By:Ca ...

  8. HBase应用开发回顾与总结系列之四:HBase配置管理类接口设计

      利用Eclipse进行HBase应用开发时,至少需要确定三个配置信息,如下表所示: #hbase config #HMaster服务部署主机及端口号 hbase.master=hdp-wuyong ...

  9. 无线客户端框架设计(3):基类的设计(iOS篇)

    本文代码:YoungHeart-Chapter-03.zip 没有基类的App都不是好App. 因为iOS使用的是mvc模式的开发模式,所以,业务逻辑基本都在每个页面相应的ViewController ...

随机推荐

  1. Minimum_Window_Substring两种方法求解

    题目描述: Given a string S and a string T, find the minimum window in S which will contain all the chara ...

  2. I²C接口学习总结

    1.IIC总线概念:   a.只有两条总线线路:一条串行数据线,一条串行时钟线.   b.每个连接到总线的器件都可以使用软件根据它们的唯一的地址来识别.   c.传输数据的设备间是简单的主从关系.   ...

  3. seafile安装日志(非教程)

    需要的软件: python 2.7.x(从 Seafile 5.1 开始,python 版本最低要求为2.7) python-setuptools python-imaging python-mysq ...

  4. [cocoapods]cocoapods问题解决

    错误1. While executing gem no such name 错误原因:gem 网址被挡住了. 解决办法:设置https://ruby.taobao.org/ 详情参考 http://w ...

  5. 无刷新分页 jquery.pagination.js

     无刷新分页 jquery.pagination.js 采用Jquery无刷新分页插件jquery.pagination.js实现无刷新分页效果 1.插件参数列表 http://www.dtan.so ...

  6. 248. Strobogrammatic Number III

    题目: A strobogrammatic number is a number that looks the same when rotated 180 degrees (looked at ups ...

  7. EJB--事务管理 .

    在我们对事务的基本概念以及出现的问题和隔离级别有进一步的了解之后,接下来看看EJB是如何进行事务管理. 在EJB中有两种使用事务的方式.第一种方式通过容器管理的事务,叫CMT(Container-Ma ...

  8. MyEclipse +Tomcat 异常操作

    安装完MyEclipse 2014,用JAX-WS的方式写了一个小段Web Service,用MyEclipse 自带的 Tomcat 部署没有问题,用我自己的,却出现下面的错误: java.lang ...

  9. dp,px转换

    public static int dip2px(Context context, float dpValue) {        final float scale = context.getRes ...

  10. sql server2005内存过高释放方法

    最近做了一个网站qq.115sou.com,在服务器中SQL Server占用内存非常高,加内存后,SQL Server又吃掉新加的内存,好像内存永远不够用一样,怎么办? 其实这并不一定是由于SQL ...