【C++】学习笔记四十七——类的构造函数和析构函数
来源:互联网 发布:淘宝跳蚤 编辑:程序博客网 时间:2024/04/28 21:21
构造函数
类构造函数用来构造新对象,并将值赋给它们的数据成员。
构造函数的名称与类名相同。
程序在声明对象时,将自动调用构造函数。
构造函数的原型和函数头有一个有趣的特征:没有返回值,但没有被声明为void类型。实际上,构造函数没有声明类型。
1.声明和定义构造函数
以Stock为例,由于需要为Stock对象提供3个值,因此应为构造函数提供3个参数。一种可能的定义如下:
Stock::Stock(const string & co, long n, double pr){ company = co; if (n<0) { std::cout << "Number of shares can't be negative; " << company << " shares set to 0.\n"; shares = 0; } else shares = n; share_val = pr; set_tot();}
2.使用构造函数
有两种使用构造函数来初始化对象的方式。第一种是显式地调用构造函数:
Stock food = Stock("World Cabbage", 250, 1.25);
另一种方式是隐式地调用构造函数:
Stock garment("Furry Mason", 50, 2.5);
每次创建类对象(包括使用new动态分配内存),都会使用类构造函数。
Stock *pstock = new Stock("Electroshock Games", 18, 19.0);
构造函数的使用方式不同于其他类方法,一般来说,使用对象来调用方法:
stock1.show();
但无法使用对象来调用构造函数,因为在构造函数构造出对象之前,对象是不存在的。
3.默认构造函数
默认构造函数是在未提供显式初始值时,用来创建对象的构造函数:
Stock fluffy_the_cat;
如果没有提供任何构造函数,则C++将自动提供默认构造函数。它是默认构造函数的隐式版本,不做任何工作。如:
Stock::Stock() {}
奇怪的是,当且仅当没有定义任何构造函数时,编译器才会提供默认构造函数。为类定义了构造函数后,程序员就必须为它提供默认构造函数。如果提供了非默认构造函数(如Stock(const char * co, int n, double pr)),但没有提供默认构造函数,则下面的声明将出错:
Stock stock1;
这样做的原因可能是想禁止创建未初始化的对象。然而,如果要创建对象,而不显式地初始化,则必须定义一个不接受任何参数的默认构造函数。定义默认构造函数的方式有两种,一种是给已有构造函数的所有参数提供默认值:
Stock(const string & co="Error",int n=0,double pr=0.0);
另一种方式是通过函数重载来定义另一个构造函数——一个没有参数的构造函数:
Stock();
由于只能有一个默认构造函数,因此不能同时采用这两种方式。实际上,通常应初始化所有的对象,以确保所有成员一开始就有已知的合理值。因此,用户定义的默认构造函数通常给所有成员提供隐式初始值:
Stock::Stock(){ company = "no name"; shares = 0; share_val = 0.0; total_val = 0.0;}
使用上述任何一种方式创建了默认构造函数后,便可以声明对象变量,而不对他们进行显式初始化:
Stock first;Stock first = Stock();Stock *prelief = new Stock;
不要被非默认构造函数的隐式形式所误导:
Stock first("Concerete Conglomerate"); //调用非默认构造函数Stock second(); //一个返回Stock对象的函数Stock third; //隐式地调用默认构造函数,不用括号
析构函数
由构造函数创建对象后,程序负责跟踪该对象;对象过期时,程序将自动调用一个特殊的成员函数——析构函数。
析构函数完成清理工作,实际上非常有用。例如,如果构造函数用new来分配内存,则析构函数使用delete来释放内存,
析构函数的名称:在类名前加~
和构造函数一样,析构函数也可以没有返回值和声明类型。与构造函数不同的是,析构函数没有参数。因此,Stock析构函数的原型为:
~Stock();
何时调用析构函数应由编译器决定,通常不应在代码中显式地调用析构函数。
程序10.4 stock10.h
#ifndef STOCK10_H_#define STOCK10_H_#include <string>class Stock{private: std::string company; long shares; double share_val; double total_val; void set_tot() { total_val = shares * share_val; }public: //two constructors Stock(); Stock(const std::string & co, long n = 0, double pr = 0.0); ~Stock(); void buy(long num, double price); void sell(long num, double price); void update(double price); void show();};#endif
程序10.5 stock10.cpp
#include <iostream>#include "stock10.h"//constructorsStock::Stock(){ std::cout << "Default constructor called\n"; company = "no name"; shares = 0; share_val = 0.0; total_val = 0.0;}Stock::Stock(const std::string & co, long n, double pr){ std::cout << "Constructor using " << co << " called\n"; company = co; if (n < 0) { std::cout << "Number of shares can't be negative; " << company << " shares set to 0.\n"; shares = 0; } else shares = n; share_val = pr; set_tot();}//class destructorStock::~Stock(){ std::cout << "Bye, " << company << "!\n";}//other methodsvoid Stock::buy(long num, double price){ if (num < 0) { std::cout << "Number of shares purchased can't be negative; " << "Transaction is aborted.\n"; } else { shares += num; share_val = price; set_tot(); }}void Stock::sell(long num, double price) //减少持有股票{ using std::cout; if (num < 0) { cout << "Number of shares sold can't be negative; " << "Transaction is aborted.\n"; } else if (num > shares) { cout << "You can't sell more than you have! " << "Transaction is aborted.\n"; } else { shares -= num; share_val = price; set_tot(); }}void Stock::update(double price){ share_val = price; set_tot();}void Stock::show(){ std::cout << "Company: " << company << " Shares: " << shares << '\n' << " Share Price: $" << share_val << " Total Worth: $" << total_val << '\n';}
程序10.6 usestock2.cpp
#include <iostream>#include "stock10.h"int main(){ { using std::cout; cout << "Using constructors to creat new objects\n"; Stock stock1("NanoSmart", 12, 20.0); stock1.show(); Stock stock2 = Stock("Boffo Objets", 2, 2.0); stock2.show(); cout << "Assigning stock1 to stock2:\n"; stock2 = stock1; cout << "Listing stock1 and stock2:\n"; stock1.show(); stock2.show(); cout << "Using a contrustor to reset an object\n"; stock1 = Stock("Nifty Foods", 10, 50.0); cout << "Revised stock1:\n"; stock1.show(); cout << "Done\n"; } system("pause"); return 0;}
在程序10.3中main的开头和结尾多加了一个大括号,这是为了显示析构函数,否则代码块将为整个mai(),只有main()执行结束才会调用析构函数,将看不到最后两条消息。
构造函数不仅可用于初始化新对象,还可以对已存在的对象赋新值。这是通过让构造程序创建一个新的临时的对象,然后将内容复制给stock1来实现的,随后程序调用析构函数,以删除该临时对象。
C++11列表初始化
提供与某个构造函数的参数列表匹配的内容,并用大括号将它们括起:
Stock hot_tip = {"Derivatives Plus Plus", 100, 45.0};Stock jock {"Sport Age Storage, Inc"};Stock temp {};
const成员函数
对下面的代码:
const Stock land = Stock("Kludgehorn Properties");land.show();
编译器将拒绝第二行。因为show()的代码无法确保调用对象不被修改。
C++的解决方法是将const关键字放在括号后面,即:
void show() const;
函数定义的开头为:
void stock::show() const
以这种方式声明和定义的类函数被称为const成员函数。
只要类方法不修改调用函数,就应将其声明为const。
- 【C++】学习笔记四十七——类的构造函数和析构函数
- C/C++学习笔记:String类的构造函数、析构函数和赋值函数
- 【C++】学习笔记四十三——函数模板
- 学习C++——构造函数和析构函数
- C++学习笔记(4)——派生类的构造函数和析构函数
- C/C++——构造函数、复制构造函数和析构函数的执行时刻
- C/C++——构造函数和析构函数
- [c++]派生类的构造函数和析构函数
- C++:类的构造函数和析构函数
- c++---派生类的构造函数和析构函数
- 面向对象的程序设计-学习笔记-23-派生类的构造函数和析构函数
- Objective-C学习笔记---构造函数和析构函数
- Objective-C学习笔记---构造函数和析构函数
- C++——构造函数和析构函数初识
- C#—构造函数和析构函数
- C++笔记——构造函数和析构函数
- c#学习笔记-构造函数和析构函数
- C++学习笔记1:构造函数和析构函数
- 动态将所有点放在最佳视野内-百度地图
- Dijkstra 算法 -方法、算法、代码和正确性的证明
- 字符串加密
- 画图
- java学习笔记——数据库基础2
- 【C++】学习笔记四十七——类的构造函数和析构函数
- bzoj1059 矩阵游戏 二分图
- 2017 计蒜之道 初赛 第六场 !
- (1)指向常量的指针是指一个指向常量的指针变量
- 【U3D设计模式】观察者模式
- 【转载】----Maven项目错误解决小结
- kaldi003 -- log机制
- nginx负载均衡算法
- iso文件:抱歉,装载文件时出现问题