• 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;
    }
  • 相关阅读:
    linux运维学习
    2017年阿里巴巴三面经验
    Spring Boot:在Spring Boot中使用Mysql和JPA
    meshroom和alicevision在Ubuntu16上的安装过程
    ubuntu rm -rf ntfs 硬盘恢复
    python 脚本内部修改 LD_LIBRARY_PATH
    python uml 图
    tlmgr 相关
    ubuntu 安装 clangd 10.0.0
    zsh 快捷键
  • 原文地址:https://www.cnblogs.com/obama/p/3239582.html
Copyright © 2020-2023  润新知