C++中构造函数或析构函数定义为private

转自:http://www.blogjava.net/fhtdy2004/archive/2009/05/30/278971.html

  很多情况下要求当前的程序中只有一个object。例如一个程序只有一个和数据库的连接,只有一个鼠标的object。通常我们都将构造函数的声明置于public区段,假如我们将其放入private区段中会发生什么样的后果?这意味着什么?

(1)构造函数定义private
      当我们在程序中声明一个对象时,编译器为调用构造函数(如果有的话),而这个调用将通常是外部的,也就是说它不属于class对象本身的调用,假如构造函数是私有的,由于在class外部不允许访问私有成员,所以这将导致编译出错。
      然而,对于class本身,可以利用它的static公有成员,因为它们独立于class对象之外,不必产生对象也可以使用它们。
      此时因为构造函数被class私有化,所以我们要创建出对象,就必须能够访问到class的私有域;这一点只有class的成员可以做得到;但在我们建构出其对象之前,怎么能利用它的成员呢?static公有成员,它是独立于class对象而存在的,“我们”可以访问得到。假如在某个static函数中创建了该class的对象,并以引用或者指针的形式将其返回(这里不以对象返回,主要是构造函数是私有的,外部不能创建临时对象),就获得了这个对象的使用权。
      下面是例子:
class OnlyHeapClass
{
public:
   static OnlyHeapClass* GetInstance()
       {
              // 创建一个OnlyHeapClass对象并返回其指针
              return (new OnlyHeapClass);
       }
   void Destroy();
private:
       OnlyHeapClass() { }
       ~OnlyHeapClass() {}
};

int main()
{
       OnlyHeapClass *p = OnlyHeapClass::GetInstance();
       ... // 使用*p
       delete p;
       return 0;
}

这个例子使用了私有构造函数,GetInstance()作为OnlyHeapClass的静态成员函数来在内存中创建对象:由于要跨函数传递并且不能使用值传递方式,所以我们选择在堆上创建对象,这样即使getInstance()退出,对象也不会随之释放,可以手动释放。
    
      构造函数私有化的类的设计保证了其他类不能从这个类派生或者创建类的实例,还有这样的用途:例如,实现这样一个class:它在内存中至多存在一个,或者指定数量个的对象(可以在class的私有域中添加一个static类型的计数器,它的初值置为0,然后在GetInstance()中作些限制:每次调用它时先检查计数器的值是否已经达到对象个数的上限值,如果是则产生错误,否则才new出新的对象,同时将计数器的值增1.最后,为了避免值复制时产生新的对象副本,除了将构造函数置为私有外,复制构造函数也要特别声明并置为私有。
      如果将构造函数设计成Protected,也可以实现同样的目的,但是可以被继承。

(2)析构函数private

  另外如何保证只能在堆上new一个新的类对象呢?只需把析构函数定义为私有成员。
      原因是C++是一个静态绑定的语言。在编译过程中,所有的非虚函数调用都必须分析完成。即使是虚函数,也需检查可访问性。因些,当在栈上生成对象时,对象会自动析构,也就说析构函数必须可以访问。而堆上生成对象,由于析构时机由程序员控制,所以不一定需要析构函数。保证了不能在栈上生成对象后,需要证明能在堆上生成它。这里OnlyHeapClass与一般对象唯一的区别在于它的析构函数为私有。delete操作会调用析构函数。所以不能编译。
       那么如何释放它呢?答案也很简单,提供一个成员函数,完成delete操作。在成员函数中,析构函数是可以访问的。当然detele操作也是可以编译通过。 
void OnlyHeapClass::Destroy() { 
        delete this; 

    构造函数私有化的类的设计可以保证只能用new命令在堆中来生成对象,只能动态的去创建对象,这样可以自由的控制对象的生命周期。但是,这样的类需要提供创建和撤销的公共接口。
    另外重载delete,new为私有可以达到要求对象创建于栈上的目的,用placement new也可以创建在栈上。

---------------------------------------------------------------------------------------------------------------------------------
还是不懂啊:   
  1.为什么要自己调用呢?对象结束生存期时不就自动调用析构函数了吗?什么情况下需要自己调用析构函数呢?   
    比如这样一种情况,你希望在析构之前必须做一些事情,但是用你类的人并不知道,   
  那么你就可以重新写一个函数,里面把要做的事情全部做完了再调用析构函数。   
  这样人家只能调用你这个函数析构对象,从而保证了析构前一定会做你要求的动作。   
    
  2.什么情况下才用得着只生成堆对象呢?   
    堆对象就是new出来的,相对于栈对象而言。什么情况下要new,什么情况下在栈里面   
  提前分配,无非就是何时该用动态,何时该用静态生成的问题。这个要根据具体情况   
  具体分析。比如你在一个函数里面事先知道某个对象最多只可能10个,那么你就可以   
  定义这个对象的一个数组。10个元素,每个元素都是一个栈对象。如果你无法确定数   
  字,那么你就可以定义一个这个对象的指针,需要创建的时候就new出来,并且用list   
  或者vector管理起来。

---------------------------------------------------------------------------------------------------------------------------------
类中“私有”权限的含义就是:私有成员只能在类域内被访问,不能在类域外进行访问。   
    
  把析构函数定义为私有的,就阻止了用户在类域外对析构函数的使用。这表现在如下两个方面:   
    
  1.   禁止用户对此类型的变量进行定义,即禁止在栈内存空间内创建此类型的对象。要创建对象,只能用   new   在堆上进行。   
    
  2.   禁止用户在程序中使用   delete   删除此类型对象。对象的删除只能在类内实现,也就是说只有类的实现者才有可能实现对对象的   delete,用户不能随便删除对象。如果用户想删除对象的话,只能按照类的实现者提供的方法进行。   
    
  可见,这样做之后大大限制了用户对此类的使用。一般来说不要这样做;通常这样做是用来达到特殊的目的,比如在   singleton   的实现上。楼主可查找   singleton   的资料来了解它是怎么一回事。

时间: 04-01

C++中构造函数或析构函数定义为private的相关文章

C++中构造函数或析构函数定义为private(转)

通常构造函数/析构函数的声明位于public区段,如果在private会有什么样的后果? 那么,private构造函数怎么才能被用到呢?两种方法: 1.使用友元类的对象中的方法来创建它. 2.在本类中实现static方法来创建它. (1)构造函数定义private 在程序中实例化一个对象,编译器将调用构造函数.如果构造函数是private,由于在class外部不允许访问私有成员,将导致编译失败. 怎么解决这个问题呢? 对于类本身,可以利用static公有成员,因为它独立于class对象之外,不必

C#中构造函数和析构函数的用法

构造函数与析构函数是一个类中看似较为简单的两类函数,但在实际运用过程中总会出现一些意想不到的运行错误.本文将较系统的介绍构造函数与析构函数的原理及在C#中的运用,以及在使用过程中需要注意的若干事项.一.构造函数与析构函数的原理 作为比C更先进的语言,C#提供了更好的机制来增强程序的安全性.C#编译器具有严格的类型安全检查功能,它几乎能找出程序中所有的语法问题,这的确帮了程序员的大忙.但是程序通过了编译检查并不表示错误已经不存在了,在“错误”的大家庭里,“语法错误”的地位只能算是冰山一角.级别高的

PHP中构造函数和析构函数解析

构造函数 void __construct ([ mixed $args [, $... ]] ) PHP 5 允行开发者在一个类中定义一个方法作为构造函数.具有构造函数的类会在每次创建新对象时先调用此方法,所以非常适合在使用对象之前做一些初始化工作. Note: 如果子类中定义了构造函数则不会隐式调用其父类的构造函数.要执行父类的构造函数,需要在子类的构造函数中调用 parent::__construct().如果子类没有定义构造函数则会如同一个普通的类方法一样从父类继承(假如没有被定义为 p

C++C++中构造函数与析构函数的调用顺序

http://blog.csdn.net/xw13106209/article/details/6899370 1.参考文献 参考1: C++继承中构造函数.析构函数调用顺序及虚函数的动态绑定 参考2: 构造函数.拷贝构造函数和析构函数的的调用时刻及调用顺序 参考3: C++构造函数与析构函数的调用顺序 2.构造函数.析构函数与拷贝构造函数介绍 2.1构造函数 构造函数不能有返回值 缺省构造函数时,系统将自动调用该缺省构造函数初始化对象,缺省构造函数会将所有数据成员都初始化为零或空 创建一个对象

(转)PHP中构造函数和析构函数解析

--http://www.jb51.net/article/56047.htm 构造函数 void __construct ([ mixed $args [, $... ]] ) PHP 5 允行开发者在一个类中定义一个方法作为构造函数.具有构造函数的类会在每次创建新对象时先调用此方法,所以非常适合在使用对象之前做一些初始化工作. Note: 如果子类中定义了构造函数则不会隐式调用其父类的构造函数.要执行父类的构造函数,需要在子类的构造函数中调用 parent::__construct().如果

C++中构造函数和析构函数的调用顺序

一般而言,析构函数调用的顺序和构造函数调用顺序相反,但是,对象的存储类别可以改变调用析构函数的顺序.举例说明: CreateAndDestroy类的定义 CreateAndDestroy类的成员函数的定义 测试函数 构造函数和析构函数的调用顺序: 分析 全局作用域内定义的对象的构造函数,在文件内任何其他函数(包括main函数)开始执行之前调用,当main函数执行结束时,相应的析构函数被调用,如上面的Object 1. exit函数迫使程序立即结束,不执行自动对象的析构函数.当程序中检测到输入中有

c++中构造函数 、析构函数的作用域详解

我们知道,在c++中,析构函数是在函数作用域尾部执行析构函数,从而释放对象,但是有一种情况下,析构函数作用域发生变化,请看下面的例子,定义了一个Stock类,Stock类存放在stock.h中,主调用函数在stock.cpp中. stock.h 1 #include <iostream> 2 #include <string.h> 3 class Stock{ 4 private: 5 char m_company[30]; 6 int m_stock_num; 7 float m

c++中构造函数和析构函数

一.构造函数的特点 (1)构造函数是类的一个特殊的成员函数,函数名与类名相同: (2)构造函数的访问属性应该是公有(public)访问属性: (3)构造函数的功能是对对象进行初始化,因此在构造函数中只能对数据成员做初始化,这些数据成员一般为私有成员,在构造函数中一般不做初始化以外的事情: (4)构造函数可以在类内定义也可以在类外定义: (5)构造函数无函数返回类型.注意:是什么也不写,也不可写void: (6)在程序运行时,当新的对象被建立,该对象所属的类的构造函数自动被调用,在该对象生存期中也

php 中构造函数和析构函数

构造函数: 在对象实例化时被调用,一个类中只能有一个构造函数,在类中起初始化的作用. 析构函数: 在对象结束时被自动调用. 话不多说,用一段代码来说明两者的区别: <?php //定义一个类 class Person{ //添加属性: public $name; public $age; public $height; //创建一个构造函数,起初始化的作用,一个类中只能有一个构造函数 function __construct($name,$age,$height){ $this->name=$