文档章节

C++中将构造函数和析构函数定义为private的用意

Kylen
 Kylen
发布于 2012/07/30 20:57
字数 1791
阅读 1.8K
收藏 3

3 月,跳不动了?>>>

很多情况下要求当前的程序中只有一个object。例如一个程序只有一个和数据库的连接,只有一个鼠标的object。通常我们都将构造函数的声明置于public区段,假如我们将
其放入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,也可以实现同样的目的,但是可以被继承。

       另外如何保证只能在堆上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   的资料来了解它是怎么一回事。

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

Kylen
粉丝 0
博文 1
码字总数 0
作品 0
深圳
私信 提问
加载中

评论(0)

Effective C++笔记简易总结以及程序演示

4、确定对象被使用前已被初始化 在使用变量时不进行初始化是不好的行为,在程序中有可能读入一个未初始化的值就可能导致程序崩溃。 对于内置类型,保证在使用对象之前进行初始化: 对于结构体...

oldpan
2017/10/11
0
0
6-C++远征之封装篇[上]-学习笔记

C++远征之封装篇(上) 课程简介 类(抽象概念),对象(真实具体) 配角: 数据成员和成员函数(构成了精彩而完整的类) 构造函数 & 析构函数(描述了对象的生生死死) 对象复制和对象赋值 (使...

天涯明月笙
2018/07/21
0
0
python初体验(2)——面向对象篇

在学习python的面向对象时,我始终参照的是c++的面向对象机制。相对而言,python的面向对象确实更简单一些。 基础: 整数也被作为对象。前面就看到过,说所有的东西都是对象,包括函数。 属于...

晨曦之光
2012/06/06
136
0
Effective C++学习笔记-01

1.条款03:尽量使用const 1.1 const可以修饰指针,指针所指物,两者或者都不是const对象。注意const的位置,位于号左边的是修饰所指物为常量, 右边是修饰指针 const char* p = greeting //c...

亚历山大痒
2012/12/29
103
0
C++基础教程之构造函数与析构函数

构造函数 当我们需要在对象创建时初始化一些数据的时候,我们不可能提供一个普通的成员方法供程序猿在对象创建后调用。因为如果程序猿故意或者无意间忘记了调用该方法,就可能导致程序出现偏...

这个人很懒什么都没留下
2018/09/08
0
0

没有更多内容

加载失败,请刷新页面

加载更多

2048游戏的最佳算法是什么? - What is the optimal algorithm for the game 2048?

问题: I have recently stumbled upon the game 2048 . 我最近偶然发现了2048游戏。 You merge similar tiles by moving them in any of the four directions to make "bigger" tiles. 您可......

技术盛宴
57分钟前
7
0
OSChina 周一乱弹 —— 小姐姐,这tm不是犬耳娘吗!你认错了吧

Osc乱弹歌单(2020)请戳(这里) 【今日歌曲】 @薛定谔的兄弟 :分享洛神有语创建的歌单「我喜欢的音乐」: 《Drip Drip Drip》- 音乐治疗 手机党少年们想听歌,请使劲儿戳(这里) @-Eric- ...

小小编辑
今天
34
0
HTML5 小游戏开发

HTML的基础 HTML称为超文本标记语言,是一种标识性的语言。它包括一系列标签.通过这些标签可以将网络上的文档格式统一,使分散的Internet资源连接为一个逻辑整体。HTML文本是由HTML命令组成...

冯六六
今天
17
0
Filebeat快速入门

Filebeat快速入门 本笔记整理于https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-installation.html,仅做个人学习总结使用。 Filebeat是轻量级日志采集工具,经常与ELK搭配...

趣学程序
今天
38
0
基于 HTML5 Canvas 的拓扑组件 ToolTip 应用

前言 ToolTip 效果是网页制作中常见的使用特效。当用户将鼠标悬浮在某个控件上时,ToolTip 显示并向用户展示相应的提示信息;当鼠标离开时,ToolTip 隐藏。一般情况下,我们使用 ToolTip 只是...

xhload3d
今天
25
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部