C++ 类和对象(4)构造函数

C++的目标之一是让使用类对象就像使用标准类型一样,但是常规的初始化语法不适用于类似类型Stock:

int year = 2001;
struct thing
{char * pn;int m;
};
thing amabob = {"wodget",-23};
//有效初始化
Stock hot = {"Sukie's Autos,Inc.",200,50.25};
//编译错误

        不能像上面这样初始化Stock对象的原因在于,数据部分的访问状态是私有的,这意味着程序不能直接访问数据成员。程序只能通过成员函数来访问数据成员,因此需要设计合理的成员函数,才能成功地将对象初始化。

        如果使数据成员成为公有,而不是私有,就可以按刚才介绍的方法初始化类对象,但使数据成为公有的违背了类的一个主要初衷:数据隐藏。

        一般来说,最好在创建对象时对它进行初始化。例如:

Stock gift;
gift.buy(10,24.75);

        就Stock类当前的实现而言,gift对象的company成员是没有值的。类设计假设用户在调用任何其他成员函数之前调用acquire(),但无法强加这种假设。避开这种问题的方法之一是在创建对象时,自动对它进行初始化。为此,C++提供了一个特殊的成员函数——类构造函数,专门用于构造新对象,将值赋给它们的数据成员。更准确地说,C++为这些成员函数提供了名称和使用语法,而程序员需要提供方法定义。名称与类名相同。例如,Stock类一个可能的构造函数是名为Stock()的成员函数。构造函数的原型和函数头有一个有趣的特征——虽然没有返回值,但没有被声明为void类型。实际上,构造函数没有声明类型。

        构造函数:通过成员函数,为数据成员进行赋值。

声明和定义构造函数

        现在需要创建Stock的构造函数。由于需要提供3个值,因此为构造函数提供3个参数。(第四个值,total_val成员,是根据shares和share_val计算得到的,因此不必为构造函数停供这个值。)此时程序员可能指向设置company成员,而把其值设置为0;这可以使用默认参数来完成,所以函数的原型如下:

Stock(const string & co,long n = 0,double pr = 0.0);

        第一个参数是指向字符串的指针,该字符串用于初始化成员company。n和pr参数为shares和share_val成员提供值。Tips:没有返回类型。原型位于类声明的公有部分。


Stock::Stock(const std::string &co,long n,double pr)
{company = co;if(n<0){std::cout<<"Numer of shares can't be negative;"<<company<<"shares set to be 0."<<std::endl;}else {shares = n;}share_val = pr;set_tot();
}

上述代码和前面所说的函数acquire()相同。区别在于,程序声明对象时,将自动调用构造函数。


void Stock::acquire(const std::string &co,long n,double pr)
{company = co;if(n<0){std::cout<<"Numer of shares can't be negative;"<<company<<"shares set to be 0."<<std::endl;}else {shares = n;}share_val = pr;set_tot();
}

        成员名和参数名

        不要把参数名和类成员相同,否则最终写出的代码将是这样的:

shares=shares;

        为了避免这种情况,有两种方法,一种是在数据成员名中使用m_前缀;

string m_company;

        还有一种方法是,在成员名中使用后缀_:

string company_;

         使用构造函数

C++提供了两种使用构造函数来初始化对象的方式。

第一种:显式地调用构造函数:

Stock food = Stock("World Cabbage",250,1.25);

        这将food对象的company成员设置为字符串“World Cabbage”,将shares成员设置为250,以此类推。

第二种:隐式地调用构造函数

Stock garment("Furry Mason",50,2.5);

        这种格式更紧凑,它与下面的相似调用等价:

Stock garment = Stock("Furry Mason",50,2.5);

        每次创建类对象(甚至使用new动态分配内存)时,C++都使用类构造函数。下面是将构造函数与new一起使用的方法:

Stock *pstock = new Stock("Electroshock Games",18,19.0);

        这条语句创建一个Stock对象,将其初始化为参数提供的值,并将该对象的地址赋给pstock指针。在这种情况下,对象没有名称,但可以使用指针来管理该对象。

        构造函数的使用方式不同于其他类方法。一般来说,使用对象来调用方式:

stock1.show();

        但是无法使用对象来调用构造函数,因为在构造函数构造处对象之前,对象是不存在的,因此构造函数被用来创建对象,而不能通过对象来调用。

        默认构造函数

        默认构造函数是在未提供显式初始值时,用来创建对象的构造函数。例如:

Stock fluffy_the_cat;

        如果没有提供任何构造函数,则C++将自动提供默认构造函数。它是默认构造函数的隐式版本,不做任何工作,对于Stock来说,默认构造函数可能如下:

Stock::Stock(){}

        因此将创建fluffy_the_cat对象,但不初始化其成员,这和下面的语句创建x,但是没有提供值给它一样:

int x;

        默认构造函数没有参数,因为声明不包含值。

        当且仅当没有定义任何构造函数时,编译器才会提供默认构造函数。为类定义了构造函数后,程序员必须为它提供默认构造函数。如果提供了非默认构造函数,但是没有提供默认构造函数,则会出错。

        这样做的原因可能是想禁止创建未初始化的对象。然而,如果要创建对象,而不显式地初始化,则必须定义一个不接受任何参数的默认构造函数。

定义默认构造函数的方式有两种。一种是给已有构造函数的所有参数提供默认值。

另一种是通过函数重载来定义另一个构造函数——一个没有任何参数的构造函数。

        因为只能有一个默认构造函数,因此不要同时采用这两种方式。建议初始化所有对象,确保所有成员一开始就有已知的合理值。例如:

Stock::Stock()
{company = "no name";shares = 0;share_val = 0.0;total_val = 0.0;
}

        

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/89486.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Leetcode 992. K 个不同整数的子数组

文章目录 题目代码&#xff08;9.27 首刷看解析&#xff09; 题目 Leetcode 992. K 个不同整数的子数组 代码&#xff08;9.27 首刷看解析&#xff09; 滑动窗口&#xff0c;恰好转换为&#xff1a;最多K个不同的数 - 最多K-1个不同的数 class Solution { public:int subarr…

kafka伪集群部署,使用KRAFT模式

1:拉去管理kafka界面UI镜像 docker pull provectuslabs/kafka-ui2:拉去管理kafka镜像 docker pull bitnami/kafka3:docker-compose.yml version: 3.8 services:kafka-1:container_name: kafka1image: bitnami/kafka ports:- "19092:19092"- "19093:19093&quo…

测试用例的八大基本准则

测试用例的八大基本准则 测试用例的八大基本准则功能测试性能测试兼容性测试安全测试可靠性测试易用性测试数据库测试接口测试 测试案例 测试用例的八大基本准则 上节测试用例的设计中我们讨论如何设计一个测试用例&#xff0c;知道了测试用例的设计有&#xff1a;“边界值&am…

Linux命令(87)之pwd

linux命令之pwd 1.pwd介绍 linux命令pwd(全称&#xff1a;print working directory)用来列出当前目录 2.pwd用法 pwd [参数] pwd参数(了解即可&#xff0c;99.99%用不到) 参数说明-L显示逻辑路径-P显示实际物理路径 3.实例 3.1.显示当前目录 命令&#xff1a; pwd [ro…

如何制作gif动图gif (多图合成gif、GIF录制软件、视频制作成GIF动图)

文章目录 1 在线制作多图合成gif动画2 GIF录制软件3 将现有的视频 制作成GIF动图 1 在线制作多图合成gif动画 在线制作gif动画链接:https://www.matools.com/gif ①选择需要制作gif动画的图片将其添加 ②调整时间间隔&#xff0c;图片宽高等设置 ③一键生成gif ④下载到本…

目标检测YOLO实战应用案例100讲-区域卷积网络在阴影环境目标检测上的研究与应用(下)

目录 5.2 阴影检测模块与街景检测模块实验设置 5.2.1 实验环境与工具 5.2.3 损失函数 5.2.4 实验具体流程 5.3 实验评估与对比 5.3.1 两类实验的评估标准 5.3.2 两类实验结果对比 阴影环境下街景目标检测系统的实现 6.1 系统概述 6.2 系统软硬件环境 6.3 功能模块设计 6.4 系统…

【OpenSSH漏洞修复】升级到openssh9.4p1版本

实战环境 操作系统:Centos7.9 openssh版本:7.4 重要的升级文件 使用rpm包升级 D:\Linux基线离线安装包\openssh9.4-升级包 的目录openssh-9.4p1-4.el7.x86_64.rpm openssh-clients-9.4p1-4.el7.x86_64.rpm openssh-server-9.4p1-4.el7.x86_64.rpm需要自己去官网下载离线rp…

自定义子组件的v-model

一、传统的父子传参 作为前端程序员&#xff0c;我们在开发时&#xff0c;用到最多的就是父子传参了吧&#xff0c;这一点相信大家都很熟悉了&#xff0c;在这里简单的说一下 1.父传子 &#xff08;1&#xff09; 在父组件中引入子组件&#xff0c;并在父组件的components中注…

基于PLE结合卡尔曼滤波的RSSI定位算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 MATLAB2022a 3.部分核心程序 ............................................................... for Num_xb Num_xb2Num_…

C++思考和一些代码规范(09/28)

文章目录 一、C的一些思考记录1&#xff09;C函数进化&#xff08;函数->函数指针->函数模板->仿函数|函数对象->lambda表达式&#xff09; 一、C的一些思考记录 1&#xff09;C函数进化&#xff08;函数->函数指针->函数模板->仿函数|函数对象->lamb…

golang: Code of Conduct

目录 1. golang: Code of Conduct 1. golang: Code of Conduct Go Community Code of Conduct

目标检测YOLO实战应用案例100讲-面向路边停车场景的目标检测(下)

目录 4.3 引入正则化方法 4.3.1 正则化方法原理 4.3.2 何处引入正则化方法

小白vite+vue3搭建项目整个流程

第一步 查看npm 版本npm -v&#xff0c;npm版本是7&#xff0c;创建项目命令&#xff1a; npm create vitelatest threejsVue -- --template vue第二步 // 进入项目名为threejsVue的项目命令 cd threejsVue // 安装路由 npm install vue-router4 // 安装css npm install -D s…

Unity之VR如何实现跟随视角的UI

前言 我们在制作VR项目的时候,大部分时候,是把UI固定到一个位置,比如桌子或者空中,这么做固然稳定,但是当我们有以下需求的时候,固定位置的UI可能会不适用: 1.场景较小,操作物体占用了很大体积,没有固定的可以清晰显示完整UI的位置。 2.需要频繁的前后左右,更换姿势…

外贸企业网站做谷歌SEO优化没转化怎么办?

如果您的外贸企业网站在经过谷歌SEO优化后仍然没有获得预期的转化效果&#xff0c;这可能意味着您的优化策略需要重新审视和调整。以下是谷歌seo优化服务商九凌网络的一些建议&#xff0c;帮助您解决这个问题&#xff1a; 1. 重新定义目标关键词 首先&#xff0c;确保您了解您的…

【Qt】QTabWidget如何添加控件到Tab页水平位置

在开发中&#xff0c;QTabWidget控件经常出现在项目或软件中&#xff0c;有时为了美观兼顾操作便利&#xff0c;需要把按钮或其他控件添加到QTabWidget控件的Tab页水平位置。 实现思路&#xff1a; 查看帮助文档&#xff0c;发现该类有个方法void setCornerWidget()可以实现所…

【QT+CUDA】QT中使用cuda,QT+VS+cuda下载安装配置

文章目录 相关网址汇总&#xff1a; 一、软件安装&#xff1a;VS、CUDA、QT1 安装VS1.1 下载1.2 vs2017安装1.3 vs2015安装 2 安装CUDA2.1 下载2.2 安装2.3 测试2.4 卸载 3 安装QT3.1 下载3.2 安装 二、QT使用cuda1 .pro文件 三、常用操作1 NVIDIA控制面板&#xff1a;显卡、驱…

el-collapse 嵌套中 el-checkbox作为标题,选中复选框与el-tree联动

<el-drawertitle"应用授权":visible.sync"menuDrawer"><el-collapse accordion style"padding: 15px"><el-collapse-item v-for"item in platList"><template slot"title"><el-checkbox v-model…

力扣刷题-链表-环形链表

具体题目与思路见&#xff1a;https://programmercarl.com/0142.%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8II.html#%E6%80%9D%E8%B7%AF 该文章详细介绍了如何寻找环入口点&#xff0c;以及数学原理。 class ListNode(object):def __init__(self, x):self.val xself.next Nonecl…

brew 常用命令

安装&#xff1a; /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"卸载&#xff1a; sudo /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/uninstall)&qu…