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

2023-11-02

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   的资料来了解它是怎么一回事。

分类: c/c++


转载于:https://my.oschina.net/u/1419872/blog/349054

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

随机推荐

  • 数据仓库主题九-(事务事实表)

    事务事实表 对于单事务事实表 一个业务过程建立一个事实表 只反映一个业务过程的事实 对于多事务事实表 在同一个事实表中反映多个业务过程 多个业务过程是否放到同一个事实表中 订单作为交易行为的核心载体 直接反应了交易的状况 订单的流转回产生很
  • vue + element-ui el-form-item循环校验及 el-table和el-form表单校验嵌套使用

    vue element ui el form item循环校验及 el table和el form表单校验嵌套使用 第一种 可以无限循环无限嵌套 支持同步异步 更加灵活 拓展性更强 另一种 每个form item都当成一个form 然后循环
  • makefile学习2

    变量赋值 基本赋值 与位置无关 可能被后面的语句改变 覆盖之前的值 与位置有关 是如果没有被赋值过就赋予等号后面的值 是添加等号后面的值 strip函数 strip STRINT 函数名称 去空格函数 strip 函数功能 去掉字串 若干单
  • 阿里钉钉Android实习面试也太太太太难了吧,对算法的要求堪比字节

    本人研究生在读 在2月26日找了师兄内推阿里钉钉团队 28号接到了约1面的电话 幸好我提前准备了一个多月的样子 刷面试题 刷LeetCode 面了之后才觉得自己刷少了 对于我这样一个实习生来说题目还是有些偏难 不过在4月20号终于拿到意向书
  • 对话MVP

    换位思考 我想到通过知识分享来帮助更多开发者解决开发细节问题 林宣名 开源社区成立以来 吸引汇聚了许多热爱分享 交流的技术爱好者 为感谢大家一路以来对FISCO BCOS的支持与贡献 社区开放FISCO BCOS MVP认定 以鼓励为开源社
  • MySQL-SQL InnoDB引擎 (下)

    作者 小刘在C站 个人主页 小刘主页 努力不一定有回报 但一定会有收获加油 一起努力 共赴美好人生 学习两年总结出的运维经验 以及思科模拟器全套网络实验教程 专栏 云计算技术 小刘私信可以随便问 只要会绝不吝啬 感谢CSDN让你我相遇 前言
  • 2023最新软件测试面试题大全(包含答案)

    前言 在我认为 对于测试面试以及进阶的最佳学习方法莫过于刷题 博客 书籍 视频 总结 前几者博主将淋漓尽致地挥毫于这篇博客文章中 至于总结在于个人 实际上越到后面你会发现面试并不难 其次就是在刷题的过程中有没有去思考 刷题只是次之 这又是一
  • vue json数据可视化展示

    使用vue json viewer插件 官网地址 https www npmjs com package vue json viewer 安装vue json viewer插件 npm install vue json viewer sav
  • 文件映射mmap简单设置文件大小(lseek (ftruncate可以设置文件大小))__使用mmap即文件映射实现文件的快速复制代码

    lseek fd pagesize 10 100 SEEK SET lseek应该是文件指针移动到的位置 why mmap1是文件的长度呢 lseek 是获取文件的长度 移动到最后 则是文件的总长 如lseek fd 80 1 write
  • js获取当前时间(昨天、今天、明天)

    1 时间格式化 1 昨天的时间 2 var day1 new Date 3 day1 setTime day1 getTime 24 60 60 1000 4 var s1 day1 getFullYear day1 getMonth 1
  • 【牛客网机试】写出一个程序,接受一个十六进制的数,输出该数值的十进制表示。

    题目描述 写出一个程序 接受一个十六进制的数 输出该数值的十进制表示 输入描述 输入一个十六进制的数值字符串 注意 一个用例会同时有多组输入数据 请参考帖子https www nowcoder com discuss 276处理多组输入的问
  • 起名字!

    五一假期没有出去 闲来找了以下名字 仅以参考 黄哲轩 黄凯轩 黄良宇 黄思禾 黄景龙 黄作湛 黄沐东 黄阳棣 黄骁辉 黄浩锭 黄雷星 黄海城 黄文冰 黄箫程 黄海泽 黄鑫群 黄子铭 黄嘉涛 黄智豪 黄之维 黄逸鑫 黄培祺 黄圣东 黄曙橙 黄
  • 快速入门高斯过程(Gaussian process)回归预测

    前言 这篇文章主要是教会你如何快速了解高斯过程进行回归预测的 并没有太多的公式推导 只有简单的相关的概念的介绍 如果您要自己掌握并使用高斯过程进行一个简单的预测 当然还需要进行一些基础知识学习的 我会在文章最后推荐一些博主有关高斯过程详细介
  • 【Rust 基础篇】Rust Never类型:表示不会返回的

    题解 牛群的重新排列 import java util public class ListNode int val ListNode next 题解 二叉树之寻找第k大 考察二叉树的深度优先遍历 二叉搜索树中序遍历后可以得到升序的序列 所以
  • 常见算法 - 按大小合并多个有序链表

    leetcode 23 Merge k sorted linked lists and return it as one sorted list Analyze and describe its complexity Example Inp
  • csdn百科

    csdn编辑 CSDN创立于1999年 是中国最大的IT社区和服务平台 为中国的软件开发者和IT从业者提供知识传播 职业发展 软件开发等全生命周期服务 满足他们在职业发展中学习及共享知识和信息 建立职业发展社交圈 通过软件开发实现技术商业化
  • 【逻辑】笔面试

    1 二进制问题 1 1 毒药问题 问题 有1000个一模一样的瓶子 其中有999瓶是普通的水 有1瓶是毒药 任何喝下毒药的生命都会在一星期之后死亡 现在你只有10只小白鼠和1个星期的时间 如何检验出哪个瓶子有毒药 首先一共有1000瓶 2的
  • web 基本标签

    浏览器 内核 渲染引擎 js引擎 外壳 5大常用浏览器 chrome 谷歌 内核 webkit blink FireFox 火狐 内核 Gecko Safiri 苹果 内核 webkit opear 欧朋 欧洲 挪威 内核 Presto I
  • k8s进阶篇-云原生存储ceph

    第一章 Rook安装 rook的版本大于1 3 不要使用目录创建集群 要使用单独的裸盘进行创建 也就是创建一个新的磁盘 挂载到宿主机 不进行格式化 直接使用即可 对于的磁盘节点配置如下 做这个实验需要高配置 每个节点配置不能低于2核4G k
  • zz: C++中构造函数或析构函数定义为private

    2019独角兽企业重金招聘Python工程师标准 gt gt gt C 中构造函数或析构函数定义为private 转自 http www blogjava net fhtdy2004 archive 2009 05 30 278971 ht