• C++中定义使用受限的类


    1、只能在堆上使用的类

    栈上对象通过自动调用析构函数释放空间,将该类的析构函数定义为private就可以阻止其被自动调用,从而阻止在栈上使用该类的对象,为了避免资源泄漏问题,在堆上使用该类的对象时我们必须手动调用其析构函数。代码如下。

    #include <iostream>
    using namespace std;
    
    class CHeapOnly {
    public:
        CHeapOnly() {
            cout << "Constructor of CHeapOnly" << endl;
        }
        void Destroy() const {
            delete this;
        }
    private:
        ~CHeapOnly() {
            cout << "Destructor of CHeapOnly" << endl;
        }
    };
    
    int main() {
        CHeapOnly* pHeap = new CHeapOnly;
        pHeap->Destroy();
    
        //CHeapOnly objHeap; //error
    
        return 0;
    }
    

    2、只能在栈上使用的类

    堆上对象的析构需要调用delete operator,delete operator会调用析构函数,然后调用operator delete,operator delete是函数且可以被重载,将operator delete定义为private就可以阻止堆上对象的析构,从而阻止其在堆上使用。类似的,我们可以将operator new定义为private阻止堆上创建该类的对象,因为堆上创建对象需要调用new operator,new operator会调用operator new,然后调用类的构造函数。

    #include <iostream>
    using namespace std;
    
    class CStackOnly {
    public:
        CStackOnly() {
            cout << "Constructor of CStackOnly" << endl;
        }
        ~CStackOnly() {
            cout << "Destrucotr of CStackOnly" << endl;
        }
    private:
        void* operator new(size_t size) {
        }
        void operator delete(void * pointee) {
        }
    };
    
    int main() {
        CStackOnly objStack;
    
        //CStackOnly* pStack = new CStackOnly; //error
    
        return 0;
    }
    

    3、不能被继承的类

    构建派生类对象时会调用基类的构造函数,将一个类的的构造函数定义为private就可以阻止被继承。那么如何生成该类的对象呢?这时可以一个工厂方法。
    还有一种方法类似boost::noncopyable,代码如下,我们需要使用虚基类的性质,虚基类的构造是由most derived class负责,具体请参考《深度探索C++对象模型》第210页,书中指出“constructor的函数本体因而必须条件式地测试传进来的参数,然后决定调用或者不调用相关的virtual base class constructors”,也指出“只有当一个完整的class object被定义出来时,它才会被调用;如果object只是某个完整object的subject,它就不会被调用”,换句话说就是most-derived class才会调用虚基类的构造函数。

    #include <iostream>
    using namespace std;
    
    class CNonderivable;
    class CNonderivableHelper
    {
    private:
        friend class CNonderivable;
        CNonderivableHelper(){};
    };
    class CNonderivable:private virtual CNonderivableHelper {
    public:
        CNonderivable(){};
        ~CNonderivable(){};
    };
    
    class Derived:public CNonderivable {
    
    };
    
    int main() {
        CNonderivable x;
        //Derived y; //error
        return 0;
    }
    

    4、不能执行拷贝或赋值的类

    拷贝和赋值需要调用拷贝构造函数和赋值运算符,如果将这两个函数声明为private就可以阻止执行拷贝或赋值,更好的方法是像boost::noncopyable一样,或者使用C++中的delete关键词,然后继承这个类。需要注意的是,将拷贝构造函数和赋值运算符声明为private的,只能阻止用户代码不能拷贝这个类型的对象,但是友元和成员函数仍旧可以拷贝对象,为了阻止友元和成员函数进行拷贝,我们只能声明不能定义它们。

    //方法1
    class Uncopyable {
    public:
        Uncopyable() {}
    
    private:
        Uncopyable(const Uncopyable&);
        Uncopyable& operator=(const Uncopyable&);
    };
    
    //方法2
    struct NonCopyable {
        NonCopyable() = default;
        NonCopyable(const NonCopyable&) = delete;
        NonCopyable& operator=(const NonCopyable&) = delete;
    };
    
    //使用时继承上面两个类中的某一个即可
  • 相关阅读:
    Java(类与对象)
    Java(数组)动手动脑
    《大道至简》第一章阅读笔记
    Java(接口与继承)动手动脑
    《大道至简》第二章阅读笔记
    Java(String)
    Java动手动脑
    Java程序设计笔记
    控制结构(1)判断控制
    MySQL Cluster 详细配置文件(config.ini)
  • 原文地址:https://www.cnblogs.com/shuaihanhungry/p/5873598.html
Copyright © 2020-2023  润新知