zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    LeetCode "Super Ugly Number" !
    LeetCode "Count of Smaller Number After Self"
    LeetCode "Binary Tree Vertical Order"
    LeetCode "Sparse Matrix Multiplication"
    LeetCode "Minimum Height Tree" !!
    HackerRank "The Indian Job"
    HackerRank "Poisonous Plants"
    HackerRank "Kundu and Tree" !!
    LeetCode "Best Time to Buy and Sell Stock with Cooldown" !
    HackerRank "AND xor OR"
  • 原文地址:https://www.cnblogs.com/obama/p/3239582.html
Copyright © 2011-2022 走看看