博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
P9-c++对象和类-02构造函数和析构函数总结
阅读量:4046 次
发布时间:2019-05-25

本文共 4901 字,大约阅读时间需要 16 分钟。

文章目录

1. 构造函数和析构函数总结

假设有这么一个类

#include 
class Stock // class declaration{
private: std::string company; long shares; double share_val; double total_val; void set_tot() {
total_val = shares * share_val; }public: void acquire(const std::string & co, long n, double pr); void buy(long num, double price); void sell(long num, double price); void update(double price); void show();}; // note semicolon at the end

C++的目标之一是让使用类对象就像使用标准类型一样,然而,到现在为止,本章提供的代码还

不能让您像初始化int或结构那样来初始化 Stock对象。
也就是说,常规的初始化语法不适用于类型Stock:

int year = 2001; // valid initializationstruct thing {
char *pn; int m:};thing amabob = {
"wodge", -23}; // valid initializationStock hot = {
"sukie's Autos, Inc ", 200, 50.25 }; //NO! compile error

不能像上面这样初始化 Stock对象的原因在于,数据部分的访问状态是私有的,这意味着程序不能直接访问数据成员。您已经看到,程序只能通过成员函数来访问数据成员,因此需要设计合适的成员函数,才能成功地将对象初始化(如果使数据成员成为公有,而不是私有,就可以按刚才介绍的方法初始化类对象,但使数据成为公有的违背了类的一个主要初衷:数据隐藏)。

一般来说,最好是在创建对象时对它进行初始化。例如,请看下面的代码:

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

就 Stock类当前的实现而言,gift对象的 company成员是没有值的。类设计假设用户在调用任何其他成员函数之前调用 acquire(),但无法强加这种假设。

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

1. 声明和定义构造函数

现在需要创建 Stock的构造函数。

由于需要为 Stock对象提供3个值,因此应为构造函数提供3个参数(第4个值, total_val成员,是根据 shares和 share_val计算得到的,因此不必为构造函数提供这个值。)
程序员可能只想设置 company成员,而将其他值设置为0:这可以使用默认参数来完成(参见第8章)。
因此原型如下所示:

// constructor prototype with some default argumentsStock(const string &co, long n=0, double pr =0.0);

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

下面是构造函数的一种可能定义

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

上述代码和本章前面的函数 acquire()相同。

区别在于,程序声明对象时,将自动调用构造函数

2. 使用构造函数

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对象,将其初始化为参数提供的值,并将该对象的地址赋给 stock指针。在这种情况下,对象没有名称,但可以使用指针来管理该对象。我们将在第11章进一步讨论对象指针。

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

stock1.show(); //stock1 object invokes show() method

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

构造函数是一种特殊的类成员函数,在创建类对象时被调用。

构造函数的名称和类名相同,但通过函数重载,可以创建多个同名的构造函数,条件是每个函数的特征标(参数列表)都不同。另外,构造函数没有声明类型。

通常,构造函数用于初始化类对象的成员,初始化应与构造函数的参数列表匹配。例如,假设Bozo类的构造函数的原型如下:

Bozo(const char * fname,const char * lname); // constructor prototype
则可以使用它来初始化新对象:
Bozo bozetta = bozo("Bozetta","Biggens"); // primary form
Bozo fufu("Fufu","O'Dweeb"); // short form
Bozo *pc = new Bozo("Popo","Le Peu"); // dynamic object
如果编译器支持C++11,则可使用列表初始化:

Bozo bozetta = {
"Bozetta","Biggens"}; //C++11Bozo fufu("Fufu","O'Dweeb") // C++11;Bozo *pc = new Bozo{
"Popo","Le Peu"); //C++11

如果构造函数只有一个参数,则将对象初始化为一个与参数的类型相同的值时,该构造函数将被调用。例如,假设有这样一个构造函数原型:

bozo(int i)
则可以使用下面的任何一种形式来初始化对象:

Bozo dribble =bozo(44) 		// primary formBozo roon(66); 				// secondary formBozo tubby = 32; 			// special form for one-argument constructors

实际上,第三个示例是新内容,不属于复习内容,但现在正是介绍它的好时机。第11章将介绍一种关闭这项特性的方式,因为它可能带来令人不愉快的意外。

警告:接受一个参数的构造函数允许使用赋值语法将对象初始化为一个值:
Classname object = value;
这种特性可能导致问题,但正如第11章将介绍的,可关闭这项特性。

3. 接受一个参数的构造函数的例子

constructor.cpp

#include 
/* author:梦悦foundation 公众号:梦悦foundation 可以在公众号获得源码和详细的图文笔记*/using std::cout;using std::endl;class Bozo {
public: int iVar; Bozo(int i) {
cout << "i = " << i << endl; this->iVar = i; } void show();};void Bozo::show(){
cout << "iVar = " << this->iVar <
公众号:梦悦foundation---------------" << endl; Bozo dribble = Bozo(44); // primary form Bozo roon(66); // secondary form Bozo tubby = 32; // special form for one-argument constructors dribble.show(); roon.show(); tubby.show(); cout << "---------------结束--->公众号:梦悦foundation---------------" << endl;}

运行结果:

meng-yue@ubuntu:~/MengYue/c++/object_class/02$ ./constructor---------------开始--->公众号:梦悦foundation---------------i = 44i = 66i = 32iVar = 44iVar = 66iVar = 32---------------结束--->公众号:梦悦foundation---------------meng-yue@ubuntu:~/MengYue/c++/object_class/02$

可以看到,直接给类实例赋值一个整数也是可以的。

在这里插入图片描述

默认构造函数没有参数,因此如果创建对象时没有进行显式地初始化,则将调用默认构造函数。

如果程序中没有提供任何构造函数,则编译器会为程序定义一个默认构造函数;否则,必须自己提供默认构造函数。

对于未被初始化的对象,程序将使用默认构造函数来创建:

Bozo bubi;// use defaultBozo *pb = new Bozo;  // use default

就像对象被创建时程序将调用构造函数一样,当对象被删除时,程序将调用析构函数。

每个类都只能有一个析构函数。析构函数没有返回类型(连void都没有),也没有参数,其名称为类名称前加上~。例如,Bozo类的析构函数的原型如下:

// class destructor~Bozo();

如果构造函数使用了new,则必须提供使用delete的析构函数。

转载地址:http://meyci.baihongyu.com/

你可能感兴趣的文章
iOS AFN 3.0版本前后区别 01
查看>>
iOS ASI和AFN有什么区别
查看>>
iOS QQ侧滑菜单(高仿)
查看>>
iOS 扫一扫功能开发
查看>>
iOS app之间的跳转以及传参数
查看>>
iOS __block和__weak的区别
查看>>
Android(三)数据存储之XML解析技术
查看>>
Spring JTA应用之JOTM配置
查看>>
spring JdbcTemplate 的若干问题
查看>>
Servlet和JSP的线程安全问题
查看>>
GBK编码下jQuery Ajax中文乱码终极暴力解决方案
查看>>
Oracle 物化视图
查看>>
PHP那点小事--三元运算符
查看>>
解决国内NPM安装依赖速度慢问题
查看>>
Brackets安装及常用插件安装
查看>>
Centos 7(Linux)环境下安装PHP(编译添加)相应动态扩展模块so(以openssl.so为例)
查看>>
fastcgi_param 详解
查看>>
Nginx配置文件(nginx.conf)配置详解
查看>>
标记一下
查看>>
IP报文格式学习笔记
查看>>