Chinaunix

标题: 为何要把类的构造函数定义为private [打印本页]

作者: herogwt    时间: 2007-07-16 15:35
标题: 为何要把类的构造函数定义为private
如果不想产生某个类的实例,可以把这个类的构造函数声明为private,但这样做有什么实际作用,既然不想产生实例,为何还要定义这个类,在实际中有什么用途吗?

刚没写清楚,修改了下,把所有的构造函数都定义为私有的。自己google了一下,查到了不少资料,在4楼帖出来了

class Base
{
private:
    Base();
    //所有的构造函数

    ……
};


[ 本帖最后由 herogwt 于 2007-7-16 16:58 编辑 ]
作者: converse    时间: 2007-07-16 16:26
有别的途径初始化类实例,或者不想让使用者通过这个途径初始化类实例.

就你这个例子而言,作者不想使用者使用默认构造函数.
作者: coldwarm    时间: 2007-07-16 16:56
不是不产生类的实例,而是禁止在类范围之外通过这个构造函数产生类的实例。
比如说单件(singleton),它通过定义一个公有的静态成员函数来返回类的唯一实例。
作者: herogwt    时间: 2007-07-16 17:00
通常我们都将构造函数的声明置于public区段,假如我们将其放入private区段中会发生什么样的后果?没错,我也知道这将会使构造函数成为私有的,这意味着什么?



    我们知道,当我们在程序中声明一个对象时,编译器为调用构造函数(如果有的话),而这个调用将通常是外部的,也就是说它不属于class对象本身的调用,假如构造函数是私有的,由于在class外部不允许访问私有成员,所以这将导致编译出错。



    你于是说:“哈哈。”我们制造了一个似乎无法产生对象的class.哦,当然,对于class本身,我们还可以利用它的static公有成员,因为它们独立于class对象之外,我们不必产生对象也可以使用它们。嗯,看来我们还是为带有私有构造函数的类找到了一个存在的理由。不过我们不应当满足于此,因为看上去应当还有发掘的余地。



    首先我们来认真看一下是不是真的无法创建出一个具有私有构造函数的类对象。“呃,可能未必。”你现在也许会这样说。这很好,让我们再来看看为什么,没错,因为构造函数被class私有化了,所以我们要创建出对象,就必须能够访问到class的私有域;但这一点“我们”是做不到的,那么,谁能做得到呢?class的成员可以做得到;但在我们建构出其对象之前,怎么能利用它的成员呢?噢,刚才我们刚刚提到了static公有成员,它是独立于class对象而存在的,当然,它也是公有的,“我们”可以访问得到。假如在某个static函数中创建了该class的对象,并以引用或者指针的形式将其返回(不可以以值的形式返回,想想为什么),我们就获得了这个对象的使用权。下面是例子:

class WonderfulClass
{
public:
       static WonderfulClass* makeAnObject()
       {
              // 创建一个WonderfulClass对象并返回其指针

              return (new WonderfulClass);
       }
private:
       WonderfulClass() { }
};


int main()
{
       WonderfulClass *p = WonderfulClass::makeAnObject();

       ... // 使用*p


       delete p;  // Not neccesary here, but it's a good habit.

       return 0;
}


   嗯,这个例子使用了私有构造函数,但它运行得很好:makeAnObject()作为WonderfulClass的静态成员函数,尽心尽责地为我们创建对象:由于要跨函数传递并且不能使用值传递方式,所以我们选择在堆上创建对象,这样即使makeAnObject()退出,对象也不会随之蒸发掉,当然,使用完之后你可不要忘了手工将它清除。



    回到前面的思路:除了公有的static成员可以帮助我们访问私有域外,还有没有其它可以利用的“东西”?

    噢,你一定想到了使用友元,完全正确。可以使用该类的友元函数或者友元类创建其对象,这里就不举例了。



    我们知道没有人会无聊到无缘无故把一个class设为私有,然后再写一个和上面一模一样的makeAnObject()来让它的用户体验一下奇特的感觉。我们也不太相信这只是由于C++的设计原因而导致的一个“顺便的”“特殊的”“无用的”边角功能。它应当是有实际用途的。提醒一下,到了JAVA中你会更容易明白很多静态方法创建对象的原理!!!



    嗯,例如,我们想实现这样一个class:它至多只能存在一个,或者指定数量个的对象(还记得标准输入输出流库中那个独一无二的cout吗?),我们可以在class的私有域中添加一个static类型的计数器,它的初值置为0,然后再对makeAnObject()做点手脚:每次调用它时先检查计数器的值是否已经达到对象个数的上限值,如果是则产生错误,否则才new出新的对象,同时将计数器的值增1.最后,为了避免值复制时产生新的对象副本,除了将构造函数置为私有外,复制构造函数也要特别声明并置为私有。
作者: hnynes    时间: 2007-07-16 21:18
你如果看过设计模式就会知道这是单例模式.为的是只产生一个实例.比如说打印机设备.
作者: ftmduck    时间: 2011-05-02 12:02
不错,得顶一下。
作者: zhengyangas    时间: 2011-10-17 10:50
hah,第一次在论坛上看懂东西
作者: ezioma    时间: 2011-10-17 11:15
单件模式
作者: bdjiuru    时间: 2012-03-01 11:20
//这是单件的一个例子
#include <iostream>
using namespace std;

class CSingleton
{
private:
        static CSingleton *pIns;
        CSingleton()
        {
            cout<<"构造函数"<<endl;
        }
public:
        static CSingleton* GetInstance()
        {
                if(pIns==NULL)
                    new CSingleton;
                return pIns;
        }

        static void ReleaseInstance(CSingleton* p)
        {
                if(p!=NULL)
                        delete p;
        }
        void f()
        {
                cout<<"f"<<endl;
        }
};

CSingleton * CSingleton::pIns =NULL;

void main(void )
{
        CSingleton *pS1=CSingleton::GetInstance();
        pS1->f();
        CSingleton *pS2=CSingleton::GetInstance();
        //pS2->f();
                CSingleton *pS3=CSingleton::GetInstance();
                        CSingleton *pS4=CSingleton::GetInstance();

}
作者: bdjiuru    时间: 2012-03-01 11:36
#include <iostream>
using namespace std;

class CSingleton
{
private:
        static CSingleton *pIns;
        CSingleton()
        {
            cout<<"构造函数"<<endl;
        }
public:
        static CSingleton* GetInstance()
        {
                if(pIns==NULL)
                    pIns= new CSingleton;
                return pIns;
        }

        static void ReleaseInstance(CSingleton* p)
        {
                if(p!=NULL)
                        delete p;
        }
        void f()
        {
                cout<<"f"<<endl;
        }
};

CSingleton * CSingleton::pIns =NULL;

void main(void )
{
        CSingleton *pS1=CSingleton::GetInstance();
        pS1->f();
        CSingleton *pS2=CSingleton::GetInstance();
        //pS2->f();
                CSingleton *pS3=CSingleton::GetInstance();
                        CSingleton *pS4=CSingleton::GetInstance();

}




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2