笔记1:结构体的初始化
结构体初始化报错:
#include <iostream>
using namespace std;
const int STRSIZE = 30;
struct bop
{
char fullname[STRSIZE];
char title[STRSIZE];
char bopname[STRSIZE];
int prefeeence;
};
int main()
{
//以下这么写,报错
bop Bop[5];
Bop[0] = {"Wimp Macho", "JJ", "1", 0};
Bop[1] = {"Raki Rhode", "Junior Progreamer", "2", 1};
Bop[2] = {"Celia Laiter", "MISP", "3", 1};
Bop[3] = {"Hoppy Hipman", "Analyst Trainee", "4", 1};
Bop[4] = {"Pat Hand", "LOOPY", "5", 1};
return 0;
}
正确写法
书上写,必须在定义时初始化(记住)
#include <iostream>
using namespace std;
const int STRSIZE = 30;
struct bop
{
char fullname[STRSIZE];
char title[STRSIZE];
char bopname[STRSIZE];
int prefeeence;
};
int main()
{
bop Bop[5] =
{
{"Wimp Macho", "JJ", "1", 0},
{"Raki Rhode", "Junior Progreamer", "2", 1},
{"Celia Laiter", "MISP", "3", 1},
{"Hoppy Hipman", "Analyst Trainee", "4", 1},
{"Pat Hand", "LOOPY", "5", 1}
};
return 0;
}
笔记2:函数指针、深入讨论函数指针
函数指针简单代码:
#include <iostream>
using namespace std;
void estimate(int line, double (*pf)(int));
double besty(int lns);
double pam(int lns);
int main()
{
int code;
cin >> code;
estimate(code, besty);
estimate(code, pam);
return 0;
}
void estimate(int lines, double (*pf)(int))
{
cout << lines << " lines will take " << (*pf)(lines) << " hours\n";
}
double besty(int lns)
{
return 0.05 * lns;
}
double pam(int lns)
{
return 0.03 * lns + 0.0004 * lns * lns;
}
函数指针笔记:
a.
利用函数指针,
相同的 函数类型及参数 可看作一类
因此,可做参数(地址传递给estimate函数,不需要重复编写estimate函数)
b.
函数指针原型:
double (*pf)(int)
*pf与pf等价
double pf(int)【与上述等价,建议写第一种,便于理解】
c.
double besty(int lns);
double (*pf)(int));
double pam(int lns);
可简单看作 pf = besty, pf = pam
深入探讨函数指针:
#include <iostream>
using namespace std;
const double *f1(const double *ar, int n);
const double *f2(const double ar[], int n);
const double *f3(const double ar[], int n);
int main()
{
double av[3] = {1112.3, 1524.6, 2227.9};
//part1:
//p1:pointer to a function
const double *(*p1)(const double *, int) = f1;
cout << "PART1:----------------\n";
cout << "Address value\n";
cout << (*p1)(av, 3) << ": " << *(*p1)(av, 3) << endl;
//part2:
//pa is an array of pointers
const double *(*pa[3])(const double *, int) = {f1, f2, f3};
cout << "PART2:----------------\n";
cout << "Address value\n";
for(int i = 0; i < 3; i++)
cout << pa[i](av, 3) << ": " << *pa[i](av, 3) << endl;
//part3
//pd is a pointer to an array of function pointers
const double *(*(*pd)[3])(const double *, int) = &pa;
cout << "PART3:----------------\n";
cout << "Address value\n";
cout << (*pd)[2](av, 3) << ": " << *(*pd)[2](av, 3) << endl;
return 0;
}
const double *f1(const double *ar, int n)
{
return ar;
}
const double *f2(const double ar[], int n)
{
return ar + 1;
}
const double *f3(const double ar[], int n)
{
return ar + 2;
}
深入探讨函数指针笔记:
part1:
const double *(*p1)(const double *, int) = f1;
如何理解以及书写:
f1 是函数名(地址),p1是函数指针
a. 首先p1是一个指针
*p1
b. 指针是什么类型,函数类型指针
const double * (*p1)(const double *, int ) = f1;
可简记 : p1 = f1;
part2:
const double *(*pa[3])(const double *, int) = {f1, f2, f3};
如何理解以及书写
a. 首先pa 是一个数组,且有3个元素
pa[3]
b. 每个元素又是指针
*pa[3]
c. 每个指针又是函数指针类型
const double * (*pa[3]) (const double *, int) = {f1, f2, f3};
可简记 pa[3] = {f1, f2, f3};
part3:
const double *(*(*pd)[3])(const double *, int) = &pa;
如何理解以及书写:
a. 首先pd是一个地址
*pd
b. 这个地址有3个元素
(*pd)[3]
c. 这3个元素又是指针
*(*pd)[3]
d. 并且指针又是函数指针类型
const double *(*(*pd)[3])(const double *, int) = &pa;
可简记: pd = &pa;
递推: *pd = pa;
*(*pd) = pa[0];
cout << (*pd)[2](av, 3) << ": " << *(*pd)[2](av, 3) << endl;
如何理解:(*pd)[2](av, 3)
pd = &pa;
(*pd) = pa;
(*pd)[2] = pa[2] = f3;
因为函数指针 *pd 与函数 pd 是等价的
即(*pd)[2](av, 3) == (*(*pd)[2])(av, 3)
如何理解: (*(*pd)[2])(av, 3)
(*pd) == pa;
(*pd)[2] == pa[2]
pa[2] 相当于指向 f3 的指针,
因为函数指针有两种写法,你可以直接用函数指针来操作,还可以用指针里面的内容来操作,
二者是等价的。
取出pa[2]里面的内容:*pa[2],即(*(*pd)[2])
为什么不写成*(*pd)[2]
首先:*pd == pa
转化:
*pa[2](av, 3) 与 (*pa[2])(av, 3)进行对比
*pa[2](av, 3):
pa[2] == f3
* f3(av, 3) 表示数组第3个元素的值
(*pa[2])(av, 3):
pa[2] == f3
*pa[2] == f3
因为 pa[2] == *pa[2]
f3(av, 3) 表示数组第3个元素的地址。
笔记3:无限输入字符串,遇到空白行结束
判断空白行:
1 cin
2 strcmp(str, '') == 0
str == ''
代码1: char数组
#include <iostream>
using namespace std;
int main()
{
char str[30];
while(cin.get(str, 30))
{
cout << "^^^^^^^^^^^^^^^^^\n";
cout << str << endl;
cin.get();
}
return 0;
}
代码2:string类
#include <iostream>
using namespace std;
int main()
{
string str;
cout << "Please enter a line: ";
getline(cin, str);
while(cin)
{
cout << "^^^^^^^^^^\n";
cout << str << endl;
cout << "Please enter next line: ";
getline(cin, str);
}
return 0;
}
笔记4:
按值传递、指针、引用何时使用:
如果传递的是数组,就用指针
如果传递的是类,就用引用
如果传递的是结构体,指针和引用都可以
如果传递的是基本类型,不想修改,就用按值传递,需要修改,用指针。
笔记5:
左值引用、右值引用简单概念:
#include <iostream>
using namespace std;
int main()
{
int a = 10;
int b = 20;
//int &c = a; //ture,左值引用
//int &d = 10; //error,左值引用:赋值运算符左右边都要是左值
//int &d = a + b; //error,同上
//int *p = &10 //error,不能对10取地址
//int *p = &(a + b); //error,不能对a + b取地址
//const int &d = 10; //true,常引用,只能通过引用读数据,不能修改引用,
//const int &c = (a + b); //true,功能被限制,解决办法,C++11引用右值引用概念
int &&x = 10; //true,右值引用,具体功能见18章
int &&y = (a + b); //true,同上
return 0;
}
/*
左值、右值概念
左值:凡是能对它取地址的就是左值
右值:凡是不能对它取地址的就是右值
*/
笔记6:
编写多个文件简单模板(使用类)
例题:
定义一个类来表示银行账户。数据成员包括储户姓名、账号(使用字符串)和存款。
成员函数执行操作如下:
创建一个对象并将其初始化;
显示储户姓名、账号和存款;
存入参数指定的存款;
取出参数指定的款项。
请编写一个简单的程序,演示以上操作
代码1:p1.h 【用来存放头文件和类声明】
#ifndef __P1_H__
#define __P1_H__
#include <iostream>
using namespace std;
class BankAccount
{
private:
string name;
string accountnum;
double balance;
public:
BankAccount();//初始化1(无参)
BankAccount(string client, string num, double bal);//初始化2(有参)
void show() const;
void deposit(double cash);
void withdraw(double cash);
}
#endif
代码2:p1.cpp【用来存放函数的定义】
#include "p1.h"
/*
不用再次书写,在p1.h已经写过
#include <iostream>
using namespace std;
*/
BankAccount::BankAccount()
{
name = "No name";
accountnum = "No account";
balance = 0.0;
}
BankAccount::BankAccount(string client, string num, double bal)
{
name = client;
accountnum = num;
balance = bal;
}
void BankAccount::show() const
{
cout << "name: " << name
<< ", AccountNum: " << accountnum
<< ", Balance: " << balance << endl;
}
void BankAccount::deposit(double cash)
{
balance += cash;
}
void BankAccount::withdraw(double cash)
{
balance -= cash;
}
代码3:main.cpp【主函数,以及操作【客户操作】】
#include "p1.h"
int main()
{
BankAccount ba;//隐式调用默认构造函数
//等价于:BankAccount ba = BankAccount();//显示调用
ba.show();
ba = BankAccount("Rick", "123456", 234.32); //先创建临时对象,再赋值
ba.show();
ba.deposit(200.0);
ba.show();
ba.withdraw(300.0);
ba.show();
return 0;
}
Linux上g++运行:
g++ main.cpp p1.cpp
./a.out
结果:
Name: No name, AccountNum: No account, Balance: 0
Name: Rick, AccountNum: 123456, Balance: 234.32
Name: Rick, AccountNum: 123456, Balance: 434.32
Name: Rick, AccountNum: 123456, Balance: 134.32
小结:
构造函数与默认构造函数
情况1:无编写构造函数
BankAccount ba; //true,系统会自动生成默认构造函数,但该函数{空}
情况2:编写了构造函数:BankAccount(string client, string num, double bal);
BankAccount ba; //error,没有进行类的初始化
解决办法有2种
1. 编写上述BankAccount();
2. 给参数提供默认值:BankAccount(string client = "No name", string num = "No account", double bal = 0.0);
3. 定义类的时候就使用初始化
BankAccount ba = BankAccount("Rick", "123456", 0.0);
BankAccount ba ("Rick", "123456", 0.0);