C++ Primer Plus 第十章知识点简化
1. 头文件与类的介绍
归纳点:
- 头文件
- 类的组成部分
头文件有个格式叫防卫式声明,即:
#ifndef XX_H_
、#define XX_H_
、#endif
#pragma once
。
#ifndef STOCK_H_
#define STOCK_H_
//#pragma once //二选一即可
#include <string>
using namespace std;
class Stock {
string m_company;
long m_shares;
double m_share_val;
double m_total_val;
void set_tot() {
m_total_val = m_shares * m_share_val;
}
public:
void acquire(const string& co, long n, double pr);
void buy(long num, double price);
void sell(long num, double price);
void update(double price);
void show();
};
#endif
对于上述代码写在自创的头文件里,并且没有写public的部分都是private(默认),在公有部分都是成员函数声明,下面代码则是写在cpp文件里。
#include <iostream>
#include "stock.h"
using namespace std;
void Stock::acquire(const string& company, long shares, double share_val){
m_company = company;
if (n < 0){
cout << "Number of shares can't be negative; " << m_company << " shares set to 0.\n";
m_shares = 0;
}
else
m_shares = shares;
m_share_val = share_val;
set_tot();
}
void Stock::buy(long shares, double share_val){
if (shares < 0){
cout << "Number of shares purchased can't be negative. "
<< "Transaction is aborted.\n";
}
else{
m_shares += shares;
m_share_val = share_val;
set_tot();
}
}
void Stock::sell(long shares, double share_val){
if (shares < 0){
cout << "Number of shares sold can't be negative. "
<< "Transaction is aborted.\n";
}
else if (shares > m_shares) {
cout << "You can't sell more than you have! "
<< "Transaction is aborted.\n";
}
else{
m_shares -= shares;
m_share_val = share_val;
set_tot();
}
}
void Stock::update(double share_val){
m_share_val = share_val;
set_tot();
}
void Stock::show(){
cout << "Company: " << m_company
<< " Shares: " << m_shares << '\n'
<< " Share Price: $" << m_share_val
<< " Total Worth: $" << m_total_val << '\n';
}
注意点:
- 对于类,数据项一般放在私有部分(private),成员函数一般放在公有部分(public);
- 结构(struct)默认访问类型是public,而类(class)则是private。
2. 构造函数与析构函数
归纳点:
- 构造函数的注意点;
- 默认构造函数和非默认构造函数;
- 析构函数。
①注意点
- 构造函数没有声明类型,即没有返回类型(不是void),声明类对象时就会自动调用该函数;
Stock::Stock(const string& company, long shares, double share_val){
m_company = company;
if (n < 0){
cout << "Number of shares can't be negative; " << m_company << " shares set to 0.\n";
m_shares = 0;
}
else
m_shares = shares;
m_share_val = share_val;
set_tot();
}
- 参数名不能与类成员数据相同
笔记:
②默认构造函数
默认构造函数没有参数,当没有定义任何构造函数时,编译器才会提供默认构造函数;若程序员提供了非默认构造函数,记住:一定还要再写上默认构造函数
Stock::Stock(){
}
//或者
Stock::Stock(){
m_company = "no name";
m_shares = 0;
m_share_val = 0.0;
m_total_val = 0.0;
笔记:
③非默认构造函数
和默认构造函数就差在参数上;
④析构函数
- 若构造函数用new来分配内存,那么析构函数则使用delete来释放内存;若没有new的话,析构函数就没有要完成的任务;
- 析构函数没有参数。
Stock::~Stock(){
}
3. 类的示例
#ifndef STOCK_H_
#define STOCK_H_
#include <string>
using namespace std;
class Stock {
private: // 默认private(可不写)
string m_company;
long m_shares;
double m_share_val;
double m_total_val;
void set_tot() {
m_total_val = m_shares * m_share_val;
}
public:
Stock();
Stock(const string& company, long shares = 0, double share_val = 0.0);
~Stock();
void buy(long num, double price);
void sell(long num, double price);
void update(double price);
void show();
};
#endif
#include <iostream>
#include "Stock.h"
using namespace std;
Stock::Stock(){
cout << "Default constructor called\n";
m_company = "no name";
m_shares = 0;
m_share_val = 0.0;
m_total_val = 0.0;
}
Stock::Stock(const string& company, long shares, double share_val){
cout << "Constructor using " << company << " called\n";
m_company = company;
if (shares < 0){
cout << "Number of shares can't be negative; "
<< m_company << " shares set to 0.\n";
m_shares = 0;
}
else
m_shares = shares;
m_share_val = share_val;
set_tot();
}
Stock::~Stock(){
cout << "Bye, " << m_company << "!\n";
}
void Stock::buy(long num, double price){
if (num < 0){
cout << "Number of shares purchased can't be negative. "
<< "Transaction is aborted.\n";
}
else{
m_shares += num;
m_share_val = price;
set_tot();
}
}
void Stock::sell(long num, double price){
if (num < 0)
cout << "Number of shares sold can't be negative. Transaction is aborted.\n";
else if (num > m_shares)
cout << "You can't sell more than you have! Transaction is aborted.\n";
else{
m_shares -= num;
m_share_val = price;
set_tot();
}
}
void Stock::update(double price){
m_share_val = price;
set_tot();
}
void Stock::show(){
ios_base::fmtflags orig = cout.setf(ios_base::fixed, ios_base::floatfield);
streamsize prec = cout.precision(3);
cout << "Company: " << m_company
<< " Shares: " << m_shares << '\n';
cout << " Share Price: $" << m_share_val;
// set format to #.##
cout.precision(2);
cout << " Total Worth: $" << m_total_val << '\n';
// restore original format
cout.setf(orig, ios_base::floatfield);
cout.precision(prec);
}
#include <iostream>
#include "Stock.h"
using namespace std;
int main(){
{
cout << "Using constructors to create new objects\n";
Stock stock0; // 默认构造函数初始化
stock0.show();
Stock stock1("NanoSmart", 12, 20.0); // 非默认构造函数初始化一
stock1.show();
Stock stock2 = Stock("Boffo Objects", 2, 2.0); // 非默认构造函数初始化二
stock2.show();
cout << "\nAssigning stock1 to stock2:\n";
stock2 = stock1;
cout << "\nListing stock1 and stock2:\n";
stock1.show();
stock2.show();
cout << "\nUsing a constructor to reset an object\n";
stock1 = Stock("Nifty Foods", 10, 50.0); // temp object
cout << "Revised stock1:\n";
stock1.show();
cout << "Done\n";
}
return 0;
}
输出:
Using constructors to create new objects
Default constructor called
Company: no name Shares: 0
Share Price: $0.000 Total Worth: $0.00
Constructor using NanoSmart called
Company: NanoSmart Shares: 12
Share Price: $20.000 Total Worth: $240.00
Constructor using Boffo Objects called
Company: Boffo Objects Shares: 2
Share Price: $2.000 Total Worth: $4.00
Assigning stock1 to stock2:
Listing stock1 and stock2:
Company: NanoSmart Shares: 12
Share Price: $20.000 Total Worth: $240.00
Company: NanoSmart Shares: 12
Share Price: $20.000 Total Worth: $240.00
Using a constructor to reset an object
Constructor using Nifty Foods called
Bye, Nifty Foods!
Revised stock1:
Company: Nifty Foods Shares: 10
Share Price: $50.000 Total Worth: $500.00
Done
Bye, NanoSmart!
Bye, Nifty Foods!
Bye, no name!
注意点:
- 类对象赋值时是可以直接使用
stock1=stock2
;
笔记:
4. const成员函数
先给大家提出个问题啊,如果我构造一个const 类对象,调用该类对象的成员函数的话会不会报错?
Eg. 请看下面代码:
const Stock stock0("test", 12, 20.0);
stock0.show();
分析:为什么错了?因为show()无法保证调用对象不被修改,相当于将const对象赋值到非const对象上,这是不被允许的,解决方法就是在show()后面加上
const
即可。void Stock::show() const{ ...... }
Reference:
- 《C++ Primer Plus》第六版 Stephen Prata 著