开始学习有一段时间了,还是做一些笔记吧,不像之前那样一章开一篇了,这本书所以的笔记都在里,就记一下这章该注意的东西。
感觉这样做笔记的话还是挺花费时间的,但是C++值得这么花时间。有一个好处就是为了把博客写好我不会囫囵吞枣地跳读了。不用着急吧,
1.预备知识 2.开始学习C++
C++简史和预备知识,不再累述。
3 处理数据
3.1 变量名
下面的代码会输出各种变量类型所占的字节数以及它的最大最小值。
值得注意的是头文件climits,里面包含了各个类型的最大最小值。
#include <iostream>
#include <cmath>
#include <climits>
int main()
{
using namespace std;
int n_int = INT_MAX;
short n_shot = SHRT_MAX;
long n_long = LONG_MAX;
long long n_llong = LLONG_MAX;
cout << "char:" << sizeof(char) << endl
<< "short:" << sizeof(short) << endl
<< "int:" << sizeof(int) << endl
<< "float:" << sizeof(float) << endl
<< "double:" << sizeof(double) << endl
<< "long:" << sizeof(long) << endl
<< "long long:" << sizeof(long long) << endl;
cout << "Maximum values:" << endl;
cout << "int:" << n_int << endl;
cout << "short:" << n_shot << endl;
cout << "long:" << n_long << endl;
cout << "long long:" << n_llong << endl;
return 0;
}
4 复合类型
4.2
cin.getline()
C++的新特性,但本人还是喜欢用
fget(char *, int const len, FILE *)
读取20个字符到name中
cin.getline(name, 20)
4.3 string类简介
感觉string超级好用
位于名称空间std中,所以要用的时候可以using namespace std
、
跟char数组的不同是:它可以赋值
string a;
a = "abcde";
还可以拼接
string a = "abcde", b = "fghijk";
string c = a + b; //c = "abcdefghijk";
4.3.5 其他形式的字符串字面值
C++分别用前缀L, u, U表示wchar_t, char16_t, char32_t
wchar_t title[] = L"Hello World";
char16_t name[] = u"Felonia Ripova";
char32_t car[] = U"TOYOTA"
原始字符串
R"(字符串内容)";
在这里,字符串中可以包含双引号""
如果要包含 "(
呢?
那可以这样
cout << R"+*(字符串内容)+*"
这里,以"+*(
开始字符串内容,以)+*”
结束字符串内容,这样子如果字符串中含有"(
就不会被读取。
4.4 4.5结构体,共用体
跟C语言里的差别不大
4.6枚举
enum color = {red, orage, yellow};
enum bigstep = {zero, null = 0, one, two};
// 如果不特别赋值,第一个元素等于0,之后每一个元素比前一个元素大1
// 也就是说,zero = 0, null = 0, one = 1, two = 2
说实话这个东西很少用
4.7指针和自由储存空间
用new 来分配空间,delete来释放内存
int *p;
p = new int;
delete p;
int *pd;
pd = new int [10];
delete [] pd
new与delete成对,当new了数组时,delete要加方括号,即delete [] pd
5 循环和关系表达式 6分支语句和逻辑运算符
与C语言相同,不再累述
(C++11有点更新的,抽空更一下这部分)
7 函数——C++的编程模块
与第八章一起记
8 函数探幽
还是跟C语言差不多,有一点不同就是增加了引用变量,引用符号为&,就是传过去的参数可以直接被函数访问和修改,类似于之前的指针。
以Swap函数举例
#include <iostream>
using namespace std;
void Swap(int &a, int &b)
{
int t;
t = a;
a = b;
b = t;
}
int main()
{
int a, b;
a = 3;
b = 5;
Swap(a, b);
cout << a << " " << b << endl;
return 0;
}
- 如果不希望参数被改变的话,定义函数的时候就加上const
返回结构的引用
正常函数的返回值是一个临时变量,然后赋值给承接它的左值。但是如果返回一个引用,则直接赋值,效率会高一点
#include <cstdio>
#include <iostream>
using namespace std;
struct book
{
int num;
int price;
};
book & add(book &one, book &two)
{
one.num += two.num;
return one;
//better to return a reference that was declare in main function
}
int main()
{
book one = {123, 456};
book two = {100, 0};
book three = add(one, two);
printf ("%d %d", three.num, three.price);
}
8.3 默认参数
简单说就是,定义一个函数,函数里有形参,可以给一些参数定义默认值,当调用函数的时候,如果不给已经定义默认值的参数赋值,则为默认值。
#include <iostream>
const int ArSize = 80;
char * left(const char * str, int n = 1);
int main()
{
using namespace std;
char sample[ArSize];
cout << "Enter a string:\n";
cin.get(sample, ArSize);
char *ps = left(sample, 4);
cout << ps << endl;
delete [] ps;
ps = left(sample);
cout << ps << endl;
delete [] ps;
return 0;
}
char * left(const char * str, int n)
{
if (n < 0)
n = 0;
char * p = new char[n + 1];
int i;
for (i = 0; i < n && str[i]; i++)
p[i] = str[i];
while (i <= n)
{
p[i++] = '\0';
}
return p;
}
注:必须从右到左添加默认值,也就是说,如果某个参数为默认值,则它右边的参数必须都有默认值
8.4 重载
重载的意思就是,定义若干个名称相同但是形参不同的函数,编译器会根据形参的不同类型调用对应的函数
8.5 函数模板
目前为止最刷新我认知的一部分了
模板的一个作用就是,当你要使用不同类型的参数来实现同样的算法时,模板会帮助你少写构造函数。比如Swap(int a, int b),这是交换两个int类型的变量,但是你要交换double类型呢?或者char类型?如果没有模板的话,你要重新写两个函数。
下面是用了模板的Swap
#include <iostream>
#include <cstdio>
using namespace std;
template <typename T>
void Swap(T &a, T &b)
{
T temp;
temp = a;
a = b;
b = temp;
}
int main()
{
int i = 10;
int j = 20;
Swap(i, j);
cout << i << " " << j << endl;
double a = 30;
double b = 40;
Swap(a, b);
cout << a << " " << b << endl;
return 0;
}
重载的模板
并非所有的类型都使用相同的算法,所以模板也需要重载,就好像函数的重载一样。下面程序中的两个Swap一个是交换两个变量的,一个是交换两个数组的,明显这两个算法不一样。
#include <iostream>
template <typename T>
void Swap(T &a, T &b);
template <typename T>
void Swap(T *a, T *b, int n);
void Show(int a[]);
const int Lim = 8;
int main()
{
using namespace std;
int i = 10, j =20;
cout << "i = " << i << ", j = " << j <<endl;
cout << "Using compiler-genrate int swapper" << endl;
Swap(i, j);
cout << "Now, i = " << i << ", j = " << j << endl;
int d1[Lim] = {3, 2, 4, 8, 12, 87, 40, 82};
int d2[Lim] = {43, 12, 5, 76, 43, 62, 98, 10};
cout << "d1 " << "d1" << endl;
Show(d1);
Show(d2);
Swap(d1, d2, Lim);
cout << "After swap :" << endl;
Show(d1);
Show(d2);
return 0;
}
template <typename T>
void Swap(T &a, T &b)
{
T temp;
temp = a;
a = b;
b = temp;
}
template <typename T>
void Swap(T *a, T *b, int n)
{
T temp;
for (int i = 0; i < n; i++)
{
temp = a[i];
a[i] = b[i];
b[i] = temp;
}
}
void Show(int a[])
{
using namespace std;
for (int i = 0; i < Lim; i++)
{
cout << a[i] << " ";
}
cout << endl;
}
显式具体化
用模板可以完成两个变量的交换了,但是如果是两个结构中的成员变量交换呢?那就需要再写一个具体的函数。
在下面的程序中是:template <> void Swap <job> (job &j1, job &j2);
(重点,需要记一下)
#include <cstdio>
#include <iostream>
using namespace std;
template <typename T>
void Swap(T &a, T &b);
struct job
{
char name[40];
double salary;
int floor;
};
template <> void Swap <job> (job &j1, job &j2);
void Show(job &j);
int main()
{
// cout.precision(2);
// cout.setf(ios::fixed, ios::floatfield);
int i = 10, j = 20;
Swap(i, j);
cout << i << " " << j << endl;
job sue = {"susan", 4300.2, 8};
job sidney = {"Sidney", 78060.72, 9};
Show(sue);
Show(sidney);
Swap(sue, sidney);
Show(sue);
Show(sidney);
return 0;
}
template <typename T> // write this code when you use template everytime
void Swap(T &a, T &b)
{
T temp;
temp = a;
a = b;
b = temp;
}
template <> void Swap<job>(job &j1, job &j2)
{
double t1;
int t2;
t1 = j1.salary;
j1.salary = j2.salary;
j2.salary = t1;
t2 = j1.floor;
j1.floor = j2.floor;
j2.floor = t2;
}
void Show(job & j)
{
cout << j.name << endl;
cout << j.salary << endl;
cout << j.floor << endl;
cout <<endl;
}
9 内存模型和名称空间
9.1 单独编译
将程序分为三部分:
头文件:包含结构声明和函数的原型。
源代码文件:定义结构和函数。
源代码文件:编写调用函数的代码。
9.2 存储持续性、作用域和链接性
持续性是指变量保留在内存中的时间。
- 自动变量会随着代码块的执行结束而被释放掉,自动变量也就是通常声明的普通变量。
int a; double b ;
- 静态变量在整个程序执行过程中都存在,静态变量包括:用static定义的变量,以及在函数以外定义的变量。静态变量的默认值为0。
作用域就是名称在多大的范围之内可见。
一般变量只在其所在的代码块中可见。但如果它所在的代码块中的代码块定义了一个跟它同名的变量,则它就会被屏蔽掉。
链接性分为外部链接和内部链接
其中,声明在函数之外的自动变量有外部链接
外部链接的变量可以在别的文件中用关键字extern声明,然后对其访问。
在函数内部定义的变量都没有链接性,在函数外面定义的自动变量有外部链接,在函数外面定义的静态变量有内部链接。
用new来分配的空间存在堆中,只有delete了它才会被释放掉
9.3名称空间
当你想定义两个名字一样的函数、结构体或者函数时,可以将他们放在不同的名称空间中以区别开。
#include <cstdio>
//declare namespace la which including int a
namespace la
{
int a;
}
//declare namespace re which including int a too
namespace re
{
int a;
}
int main()
{
using namespace la; //using complie
la::a = 4;
printf("%d\n", la::a);
re::a = 5;
printf("%d\n", re::a);
printf("%d\n", a); //because having using colpiled la, 'a' mean la::a;
}
10 对象和类
这部分应该会很少文字,感觉代码更好理解。
10.1过程性编程和面向对象编程
类和结构的区别:结构默认的访问类型是public,而类的默认访问类型是private
10.3类的构造函数和析构函数
构造函数的名字与类名相同,没有返回类型。可以有多个构造函数,根据参数的不同来区别。
- 没有参数的构造函数称为默认构造函数,用来初始化对象。
- 下面的代码中分别定义了默认构造函数,
10.4 this指针
this指针指向当前对象的地址。
比如你定义了一个class
class Player
{
private:
std::string team;
std::string name;
double salary;
double height;
double weight;
}
网友评论