参考: http://www.weixueyuan.net/view/6342.html

总结:

  限制对象的创建。限制创建对象时能够按照我们需要的那样创建,而不能随意的创建对象。

  类中显示地声明了任意一个构造函数,系统均不会再自动生成构造函数。

  声明为private属性的构造函数,与声明为private属性的成员变量或普通成员函数一样,在类外同样是不能访问的 

在上一节构造函数的例1中,我们提到,如果不声明默认构造函数book(),而只声明带参构造函数book(char *a, double p)的时候,语句book Alice;是无法创建对象的。无法创建的原因在上一节已经讲明,这节就不再赘述了。

不过类的构造函数的这一特性却可以用来限制对象的创建。

[例1] 还是用 book 类来说明这节的内容:

  1. class book
  2. {
  3. public:
  4. void setprice(double a);
  5. double getprice();
  6. void settitle(char* a);
  7. char * gettitle();
  8. void display();
  9. private:
  10. double price;
  11. char * title;
  12. };

首先需要知道的是我们是在什么样的情况下才需要限制对象的创建。限制对象的创建不代表我们想禁止创建对象,只是加以限制而已,限制创建对象时能够按照我们需要的那样创建,而不能随意的创建对象。

比如例1中,我们定义了一个book类,声明对象的时候自然是为了描述某一本具体的书,这个时候如果我们直接采用book a;这样的方式创建一个对象a,编译当然是不会有问题的,毕竟系统会自动生成默认构造函数的。但是这样创建的对象a能代表什么呢?指的又是哪一本书?完全不清楚!

如果这个时候我们直接调用a.display()函数,那会发生什么就不好说了,毕竟a.price和a.title都没有初始化。这就是一个比较危险的程序了。不过肯定有人会说,不是可以通过a.setprice和a.settitle函数对两个成员变量进行赋值么?不错,确实可以这么做,但是万一给忘掉了呢?

对于这样的一个类,类的设计人员如果让book a;这样的创建对象的方式不成立,并且每次创建对象的时候就必须给书本的price和title赋值,这样问题不就解决了么?

这样的想法能实现么?回答是肯定的。我们可以通过构造函数来实现这一功能。看下面的几个类的示例。

[例2] 不声明默认构造函数:

  1. class book
  2. {
  3. public:
  4. book(char *a, double p);
  5. void setprice(double a);
  6. double getprice();
  7. void settitle(char* a);
  8. char * gettitle();
  9. void display();
  10. private:
  11. double price;
  12. char * title;
  13. };

[例3] 将默认构造函数声明为 private:

  1. class book
  2. {
  3. public:
  4. book(char *a, double p);
  5. void setprice(double a);
  6. double getprice();
  7. void settitle(char* a);
  8. char * gettitle();
  9. void display();
  10. private:
  11. book(){}
  12. double price;
  13. char * title;
  14. };

在例2中,我们在类中声明了一个带参构造函数book(char *a, double p);,如此一来默认构造函数就不会被系统自动生成了,也即不会生成book(){}这个构造函数,如此一来创建对象book a;则会出现编译错误,要想正确创建对象则必须进行初始化,如book Alice(“Alice in Wonderland”, 29.9);。

除了此种手段之外,例3的做法也是可行的,我们将默认构造函数主动声明并定义,最关键的是将其设置为private属性,也就是说无法在类外进行访问,如此一来book a;同样会报出编译错误,只不过这一次的错误是因为访问权限的问题,此时如果想要声明对象,则还是必须通过public属性的带参构造函数book(char *a, double p);来声明对象。

根据上面的几个例子,我们将系统不会自动生成默认构造函数的情况总结如下:

  • 类中显式地声明了默认构造函数,无论其属性被设置为public、private还是protected,系统都不会再自动生成默认构造函数了。
  • 类中显式地声明了其它任意一个不是默认构造函数的构造函数,系统均不会再自动生成默认构造函数。

其实这两点可以总结为一点,那就是当类中显示地声明了任意一个构造函数,系统均不会再自动生成构造函数。在例2中我们是采用第二种情况避免默认构造函数的产生,从而限制了类对象的随意创建。

在C++中之所以利用构造函数限制类对象的创建,意图已经很明显了,那就是要求程序设计人员在使用类创建对象的时候能够正确地进行初始化。

声明为private属性的构造函数,与声明为private属性的成员变量或普通成员函数一样,在类外同样是不能访问的,我们可以巧妙地使用这一点,限制类对象的随意创建。

2.10 C++利用构造函数限制对象的创建的更多相关文章

  1. 《挑战30天C++入门极限》C++中利用构造函数与无名对象简化运算符重载函数

        C++中利用构造函数与无名对象简化运算符重载函数 在完整描述思想之前,我们先看一下如下的例子,这个例子中的加运算符重载是以非成员函数的方式出现的: //程序作者:管宁  //站点:www.cn ...

  2. .NET 利用反射将对象数据添加到数据库

    .NET 利用反射将对象数据添加到数据库   一些小型的项目,在不使用其他的框架(LINQ,NHibernate,EF等等框架)的前提下,这时候一些反复的增删改查就会让我们感到极其的繁琐,厌烦,为了避 ...

  3. JS的深度克隆,利用构造函数原型深度克隆

    我爱撸码,撸码使我感到快乐!大家好,我是Counter.今天来写写,JS中的深度克隆,这个在笔面试中,考的还是比较多的,主要是对象与数组的赋值,如果直接赋值的话,那么得到的是对象或者数组在堆里的地址, ...

  4. 利用查询条件对象,在Asp.net Web API中实现对业务数据的分页查询处理

    在Asp.net Web API中,对业务数据的分页查询处理是一个非常常见的接口,我们需要在查询条件对象中,定义好相应业务的查询参数,排序信息,请求记录数和每页大小信息等内容,根据这些查询信息,我们在 ...

  5. 利用实体bean对象批量数据传输处理

    利用实体bean对象批量数据传输处理 需求 现在有两方数据库表结构相同,一方A.另一个方B,现想从A处查询出多个表的数据,传输到B地保存起来. 解决方案1 最简单粗暴的方法就是,查询出A处相关表的数据 ...

  6. Java反射机制(获取Class对象的三种方式+获取Class中的构造函数进行对象的初始化+获取反射类的字段+获取反射类的一般方法)

    反射技术其实就是动态加载一个指定的类,并获取该类中的所有内容.而且将字节码文件封装成对象,并将字节码文件中的内容都封装成对象,这样便于操作这些成员,简单来说:反射技术可以对一个类进行解剖,反射大大增强 ...

  7. js系列教程2-对象、构造函数、对象属性全解

    全栈工程师开发手册 (作者:栾鹏) 快捷链接: js系列教程1-数组操作全解 js系列教程2-对象和属性全解 js系列教程3-字符串和正则全解 js系列教程4-函数与参数全解 js系列教程5-容器和算 ...

  8. C#利用反射来判断对象是否包含某个属性的实现方法

    本文实例展示了C#利用反射来判断对象是否包含某个属性的实现方法,对于C#程序设计人员来说有一定的学习借鉴价值. 具体实现代码如下: /// <summary> /// 利用反射来判断对象是 ...

  9. c++构造函数中调用构造函数---匿名对象再探

    #include<iostream> #include<string> using namespace std; class Copy_construction { publi ...

随机推荐

  1. Python 编程快速上手 第八章总结

    在下面函数中的()中,可为相对路径,也可为绝对路径. 获知当前目录,改变当前目录,查看当前目录 更改当前目录:os.getcwd() 改变当前目录:os.chdir() 查看当前目录:os.listd ...

  2. C#调用EXE

    1.问题意义 据说界面程序开发,首选C#(像lebview之类的也很好) 但是,能不能用其他语言开发核心代码,只用C#做界面?毕竟每种语言都有自己擅长的领域. 2.exe程序 比如有个example. ...

  3. 第一章 Lab

    关于Lab 教材恶意代码分析实战 课后练习恶意代码样本https://practicalmalwareanalysis.com或https://nostarch.com/malware.htm 以下是 ...

  4. 堆排序 GPLT L2-012 关于堆的判断

    题目链接:https://pintia.cn/problem-sets/994805046380707840/problems/994805064676261888 分析:这题看起来非常唬人,其实不难 ...

  5. JavaScript基础一

    1.1 javascript简介 Web前端有三层: HTML:从语义的角度,描述页面结构 CSS:从审美的角度,描述样式(美化页面) JavaScript:从交互的角度,描述行为(提升用户体验) J ...

  6. vim操作(待补充)

    :wq 存盘 + 退出 (:w 存盘, :q 退出) :e 打开新文件 :q 退出 h.j.k.l,分别控制光标左.下.上.右移一格. 按Ctrl+B:屏幕往后移动一页.[常用] 按Ctrl+F:屏幕 ...

  7. bzoj1801: [Ahoi2009]chess 中国象棋 dp

    题意:在N行M列的棋盘上,放若干个炮可以是0个,使得没有任何一个炮可以攻击另一个炮. 请问有多少种放置方法,中国像棋中炮的行走方式大家应该很清楚吧. 题解:dp[i][j][k]表示到了第i行,有j列 ...

  8. shiro缓存机制

    Shiro提供了类似于Spring的Cache抽象,即Shiro本身不实现Cache,但是对Cache进行了又抽象,方便更换不同的底层Cache实现.对于Cache的一些概念可以参考我的<Spr ...

  9. 【JS】【3】标签显示几秒后自动隐藏

    $("#XXX").show().delay(2000).hide(0); 2000,0:可选,速度,(毫秒:"slow":"fast") ...

  10. 详解 java socket

    一,网络编程中两个主要的问题 一个是如何准确的定位网络上一台或多台主机,另一个就是找到主机后如何可靠高效的进行数据传输. 在TCP/IP协议中IP层主要负责网络主机的定位,数据传输的路由,由IP地址可 ...