C++ 当构造函数是私有的时使用公共析构函数

C++ 当构造函数是私有的时使用公共析构函数,c++,destructor,public,C++,Destructor,Public,我见过这样的代码:构造函数被声明为私有,而析构函数是公共的。这种声明有什么用?析构函数是否需要是公共的,以便在继承过程中可以调用,或者它是代码中的一个bug 这个问题看起来可能有点短,但我真正想知道的是,当构造函数被私有化遵守C++规则时,是否有公共析构函数? 如果您想防止创建更多的类实例,那么就要让构造器私有。这样你就控制了虚无的创造,而不是它们的毁灭。因此,析构函数可能是公共的。首先:析构函数可以是私有的 当需要使用构造函数时具有公共析构函数 私有遵守C++规则?< /P> 这完全是C++的

我见过这样的代码:构造函数被声明为私有,而析构函数是公共的。这种声明有什么用?析构函数是否需要是公共的,以便在继承过程中可以调用,或者它是代码中的一个bug


这个问题看起来可能有点短,但我真正想知道的是,当构造函数被私有化遵守C++规则时,是否有公共析构函数?

如果您想防止创建更多的类实例,那么就要让构造器私有。这样你就控制了虚无的创造,而不是它们的毁灭。因此,析构函数可能是公共的。

首先:析构函数可以是私有的

当需要使用构造函数时具有公共析构函数 私有遵守C++规则?< /P> <>这完全是C++的工作。事实上,这个场景的一个很好的例子是单例模式,其中构造函数是私有的,析构函数是公共的。

简短回答 将构造函数创建为私有而将析构函数创建为公共有许多实际用途

您可以使用此范例来:

  • 强制引用计数
  • 实施
  • 实施
长话短说 上面我暗示,您可以使用私有构造函数和析构函数来实现几种设计模式。好吧,这里是如何

参考计数

在对象中使用私有析构函数有助于引用计数系统。这使开发人员能够更好地控制对象的生命周期

class MyReferenceObject
{
public:
    static MyReferenceObject* Create()
    {
        return new MyReferenceObject();
    }

    void retain()
    {
        m_ref_count++;
    }

    void release()
    {
        m_ref_count--;
        if (m_ref_count <= 0)
        {
            // Perform any resource/sub object cleanup.
            // Delete myself.
            delete this; // Dangerous example but demonstrates the principle.
        }
    }
private:

    int m_ref_count;

    MyReferenceObject()
    {
        m_ref_count = 1;
    }

    ~MyReferenceObject() { }

}

int main()
{
    new MyReferenceObject(); // Illegal.
    MyReferenceObject object; // Illegal, cannot be made on stack as destructor is private.

    MyReferenceObject* object = MyReferenceObject::Create(); // Creates a new instance of 'MyReferenceObject' with reference count.
    object->retain(); // Reference count of 2.
    object->release(); // Reference count of 1.
    object->release(); // Reference count of 0, object deletes itself from the heap.
}
看看代码如何几乎不可能被误用。在编译时强制执行
MySingleton
的正确使用,从而确保开发人员必须按预期使用
MySingleton

工厂

在工厂设计模式中使用私有构造函数是强制仅使用工厂来创建对象的一种重要机制

例如:

class MySingleton
{
public:
     MySingleton* Instance()
     {
        static MySingleton* instance = NULL;
        if (!instance)
        {
            instance = new MySingleton();
        }

        return instance;
     }
private:
    MySingleton() { }
    ~MySingleton() { } 
}

int main()
{
     new MySingleton(); // Illegal
     delete MySingleton::Instance(); // Illegal.
}
class MyFactoryObject
{
public:

protected:
    friend class MyFactory; // Allows the object factory to create instances of MyFactoryObject

    MyFactoryObject() {} // Can only be created by itself or a friend class (MyFactory).
}

class MyFactory
{
public:
    static MyFactoryObject* MakeObject()
    {

        // You can perform any MyFactoryObject specific initialisation here and it will carry through to wherever the factory method is invoked.
        return new MyFactoryObject();
    }
}

int main()
{
    new MyFactoryObject(); // Illegal.
    MyFactory::MakeObject(); // Legal, enforces the developer to make MyFactoryObject only through MyFactory.
}
这很强大,因为它对开发人员隐藏了
MyFactoryObject
的创建。您可以使用factory方法执行
MyFactoryObject
的任何初始化(例如:设置GUID,注册到DB中),并且在使用factory方法的任何地方,该初始化代码也将发生

总结
这只是几个示例,说明如何使用私有构造函数和析构函数强制正确使用API。如果您想变得棘手,还可以将所有这些设计模式组合起来;)

我脑海中的一个例子是,假设您希望将类实例数限制为0或1。 例如,对于某些单例类,您希望应用程序能够临时销毁对象以减少内存使用。实现此构造函数将是私有的,而析构函数将是公共的。请参阅下面的代码片段

class SingletoneBigMemoryConsumer
{
private:
    SingletoneBigMemoryConsumer()
    {
        // Allocate a lot of resource here.
    }

public:
    static SingletoneBigMemoryConsumer* getInstance()
    { 
        if (instance != NULL) 
            return instance;
        else
            return new SingletoneBigMemoryConsumer();
    }
    ~SingletoneBigMemoryConsumer()
    {
        // release the allocated resource.
        instance = NULL;
    }
private:
    // data memeber.
    static SingletoneBigMemoryConsumer* instance;
}



//Usage.
SingletoneBigMemoryConsumer* obj = SingletoneBigMemoryConsumer::getInstance();
// You cannot create more SingletoneBigMemoryConsumer here.
// After 1 seconds usage, delete it to reduce memory usage.
delete obj;
// You can create an new one when needed later

对象的所有者需要访问析构函数才能销毁它。如果构造函数是私有的,那么必须有一些可访问的函数来创建对象。如果该函数将构造对象的所有权转移给调用者(例如,返回指向空闲存储上对象的指针),则调用者在决定删除该对象时必须有权访问析构函数

顺序相反

析构函数是否需要是公共的,以便在继承过程中可以调用,或者它是代码中的一个bug

实际上,要使继承工作,析构函数至少应该受到
保护。如果您从具有
私有
析构函数的类继承,则无法为派生类生成析构函数,这实际上会阻止实例化(您仍然可以使用
静态
方法和属性)

这种声明有什么用

请注意,即使构造函数是
私有的
,在没有进一步指示的情况下,该类也有一个(默认生成的)公共复制构造函数和复制赋值运算符。这种模式在以下情况下经常出现:

  • 命名构造函数习惯用法
  • 工厂
命名构造函数习惯用法示例:

class Angle {
public:
    static Angle FromDegrees(double d);
    static Angle FromRadian(double d);

private:
    Angle(double x): _value(x) {}
    double _value;
};
由于
x
是否应精确到度数或弧度(或其他任何单位)是不明确的,因此构造函数被设置为
private
,并提供了命名方法。这样,使用使单位变得明显:

Angle a = Angle::FromDegrees(360);

一个类只有一个析构函数,但它有几个构造函数(默认、复制、移动(自C++11以来),可能还有更多用户定义的构造函数)。在您看到的代码中,是否所有构造函数都声明为私有?还有,它们是给出了定义还是没有定义?另外,您提到了继承:类是基类吗?(你可以在你的问题中添加一段代码来说明)构造函数都是私有的;默认构造函数已给出定义。我想我不能提供代码片段,因为它是一个行业代码,但是,我认为问题中的信息就足够了。如果您对基类的构造函数没有至少受保护的访问权限,那么您如何从基类“继承”该基类?关于为什么有人会将构造函数设为私有,一个常见的场景是单例模型类(呃,肮脏的词,那个单例)。静态类变量声明为相同的类类型。它可以构造,但没有其他人可以。关于是否允许使用私有析构函数,我不认为(对于“行业代码”,可以编写一个简化的示例(名称为“Foo”和snipped implementation),只是为了举例说明,但不管怎样。)查看类的实际使用方式(外部代码如何获得实例)(或指向一个的指针),其中触发了销毁),不仅在其定义上,还可以帮助您理解为什么。确切地说,单例是我在问这个问题时想到的。但是,无论在哪里解释了
Singleton
,都会生成析构函数