关于c++学习过程中的学习笔记
我本人在大一的时候学习使用过c++,现在由于准备考研,所以又准备复习一下c++,整理一下学习笔记,本人跟着菜鸟教程的c++教程复习:菜鸟教程
编辑器选择:VS是不错的选择,但是太大了,所以我选择Dev-C++,云盘链接,密码:farc。
C++实在C语言的基础上扩展而来的,他既可以面向过程,又可以面向对象,就我个人而言,我比较喜欢面向对象的使用方法,当然,具体使用什么方式就实际问题而言。
导入输入输出包:
#include <iostream>
//具体使用主要是iostream::cin,iostream::cout,etc.
命名空间的使用
//告诉编译器使用 std 命名空间。
using namespace std;
当我使用了这个命名空间之后,我就不需要iostream::cin了,直接cin就可以了。
数据类型
略
以下程序输出电脑上各种数据类型的大小:
#include<iostream>
#include<string>
#include <limits>
using namespace std;
int main()
{
cout << "type: \t\t" << "************size**************"<< endl;
cout << "bool: \t\t" << "所占字节数:" << sizeof(bool);
cout << "\t最大值:" << (numeric_limits<bool>::max)();
cout << "\t\t最小值:" << (numeric_limits<bool>::min)() << endl;
cout << "char: \t\t" << "所占字节数:" << sizeof(char);
cout << "\t最大值:" << (numeric_limits<char>::max)();
cout << "\t\t最小值:" << (numeric_limits<char>::min)() << endl;
cout << "signed char: \t" << "所占字节数:" << sizeof(signed char);
cout << "\t最大值:" << (numeric_limits<signed char>::max)();
cout << "\t\t最小值:" << (numeric_limits<signed char>::min)() << endl;
cout << "unsigned char: \t" << "所占字节数:" << sizeof(unsigned char);
cout << "\t最大值:" << (numeric_limits<unsigned char>::max)();
cout << "\t\t最小值:" << (numeric_limits<unsigned char>::min)() << endl;
cout << "wchar_t: \t" << "所占字节数:" << sizeof(wchar_t);
cout << "\t最大值:" << (numeric_limits<wchar_t>::max)();
cout << "\t\t最小值:" << (numeric_limits<wchar_t>::min)() << endl;
cout << "short: \t\t" << "所占字节数:" << sizeof(short);
cout << "\t最大值:" << (numeric_limits<short>::max)();
cout << "\t\t最小值:" << (numeric_limits<short>::min)() << endl;
cout << "int: \t\t" << "所占字节数:" << sizeof(int);
cout << "\t最大值:" << (numeric_limits<int>::max)();
cout << "\t最小值:" << (numeric_limits<int>::min)() << endl;
cout << "unsigned: \t" << "所占字节数:" << sizeof(unsigned);
cout << "\t最大值:" << (numeric_limits<unsigned>::max)();
cout << "\t最小值:" << (numeric_limits<unsigned>::min)() << endl;
cout << "long: \t\t" << "所占字节数:" << sizeof(long);
cout << "\t最大值:" << (numeric_limits<long>::max)();
cout << "\t最小值:" << (numeric_limits<long>::min)() << endl;
cout << "unsigned long: \t" << "所占字节数:" << sizeof(unsigned long);
cout << "\t最大值:" << (numeric_limits<unsigned long>::max)();
cout << "\t最小值:" << (numeric_limits<unsigned long>::min)() << endl;
cout << "double: \t" << "所占字节数:" << sizeof(double);
cout << "\t最大值:" << (numeric_limits<double>::max)();
cout << "\t最小值:" << (numeric_limits<double>::min)() << endl;
cout << "long double: \t" << "所占字节数:" << sizeof(long double);
cout << "\t最大值:" << (numeric_limits<long double>::max)();
cout << "\t最小值:" << (numeric_limits<long double>::min)() << endl;
cout << "float: \t\t" << "所占字节数:" << sizeof(float);
cout << "\t最大值:" << (numeric_limits<float>::max)();
cout << "\t最小值:" << (numeric_limits<float>::min)() << endl;
cout << "size_t: \t" << "所占字节数:" << sizeof(size_t);
cout << "\t最大值:" << (numeric_limits<size_t>::max)();
cout << "\t最小值:" << (numeric_limits<size_t>::min)() << endl;
cout << "string: \t" << "所占字节数:" << sizeof(string) << endl;
// << "\t最大值:" << (numeric_limits<string>::max)() << "\t最小值:" << (numeric_limits<string>::min)() << endl;
cout << "type: \t\t" << "************size**************"<< endl;
return 0;
}
输出结果:
type: ************size**************
bool: 所占字节数:1 最大值:1 最小值:0
char: 所占字节数:1 最大值: 最小值:?
signed char: 所占字节数:1 最大值: 最小值:?
unsigned char: 所占字节数:1 最大值:? 最小值:
wchar_t: 所占字节数:4 最大值:2147483647 最小值:-2147483648
short: 所占字节数:2 最大值:32767 最小值:-32768
int: 所占字节数:4 最大值:2147483647 最小值:-2147483648
unsigned: 所占字节数:4 最大值:4294967295 最小值:0
long: 所占字节数:8 最大值:9223372036854775807 最小值:-9223372036854775808
unsigned long: 所占字节数:8 最大值:18446744073709551615 最小值:0
double: 所占字节数:8 最大值:1.79769e+308 最小值:2.22507e-308
long double: 所占字节数:16 最大值:1.18973e+4932 最小值:3.3621e-4932
float: 所占字节数:4 最大值:3.40282e+38 最小值:1.17549e-38
size_t: 所占字节数:8 最大值:18446744073709551615 最小值:0
string: 所占字节数:24
type: ************size**************
typedef 声明
可以使用 typedef 为一个已有的类型取一个新的名字。
typedef type newname;
eg:
typedef int feet;
feet distance;
enum 枚举类型
枚举类型(enumeration)是C++中的一种派生数据类型,它是由用户定义的若干枚举常量的集合。
如果一个变量只有几种可能的值,可以定义为枚举(enumeration)类型。所谓"枚举"是指将变量的值一一列举出来,变量的值只能在列举出来的值的范围内。
创建枚举,需要使用关键字 enum。枚举类型的一般形式为:
enum 枚举名{
标识符[=整型常数],
标识符[=整型常数],
...
标识符[=整型常数]
} 枚举变量;
eg:
enum color { red, green, blue } c;
c = blue;
整数常量
整数常量可以是十进制、八进制或十六进制的常量。前缀指定基数:0x 或 0X 表示十六进制,0 表示八进制,不带前缀则默认表示十进制。
整数常量也可以带一个后缀,后缀是 U 和 L 的组合,U 表示无符号整数(unsigned),L 表示长整数(long)。后缀可以是大写,也可以是小写,U 和 L 的顺序任意。
下面列举几个整数常量的实例:
85 // 十进制
0213 // 八进制
0x4b // 十六进制
30 // 整数
30u // 无符号整数
30l // 长整数
30ul // 无符号长整数
浮点常量
浮点常量由整数部分、小数点、小数部分和指数部分组成。您可以使用小数形式或者指数形式来表示浮点常量。
当使用小数形式表示时,必须包含整数部分、小数部分,或同时包含两者。当使用指数形式表示时, 必须包含小数点、指数,或同时包含两者。带符号的指数是用 e 或 E 引入的。
下面列举几个浮点常量的实例:
3.14159 // 合法的
314159E-5L // 合法的
510E // 非法的:不完整的指数
210f // 非法的:没有小数或指数
.e55 // 非法的:缺少整数或分数
#define 预处理器
下面是使用 #define 预处理器定义常量的形式:
#define identifier value
实际上就是定义一个字符串为一个常量,方便使用的时候表示其含义,或者是统一更改。
const 关键字
以使用 const 前缀声明指定类型的常量,如下所示:
const type variable = value;
具体我也不是很理解,以后用到这个再补充吧。
static 存储类
static 存储类指示编译器在程序的生命周期内保持局部变量的存在,而不需要在每次它进入和离开作用域时进行创建和销毁。因此,使用 static 修饰局部变量可以在函数调用之间保持局部变量的值。
static 修饰符也可以应用于全局变量。当 static 修饰全局变量时,会使变量的作用域限制在声明它的文件内。
在 C++ 中,当 static 用在类数据成员上时,会导致仅有一个该成员的副本被类的所有对象共享。
这个是比较常用的,怎么说呢,就是在第一次创建这个静态变量的时候,将这个变量定义为全局变量的样子,具体效果就是这样了,肯定有更细微的不同,暂时我也用不到,建议不要使用,直接使用全局变量好了,以后遇到问题再补充。
函数传值
调用类型 | 描述 |
---|---|
传值调用 | 该方法把参数的实际值复制给函数的形式参数。在这种情况下,修改函数内的形式参数对实际参数没有影响。 |
指针调用 | 该方法把参数的地址复制给形式参数。在函数内,该地址用于访问调用中要用到的实际参数。这意味着,修改形式参数会影响实际参数。 |
引用调用 | 该方法把参数的引用复制给形式参数。在函数内,该引用用于访问调用中要用到的实际参数。这意味着,修改形式参数会影响实际参数。 |
数学运算函数
序号 函数 | 描述 |
---|---|
1 double cos(double); | 该函数返回弧度角(double 型)的余弦。 |
2 double sin(double); | 该函数返回弧度角(double 型)的正弦。 |
3 double tan(double); | 该函数返回弧度角(double 型)的正切。 |
4 double log(double); | 该函数返回参数的自然对数。 |
5 double pow(double, double); | 假设第一个参数为 x,第二个参数为 y,则该函数返回 x 的 y 次方。 |
6 double hypot(double, double); | 该函数返回两个参数的平方总和的平方根,也就是说,参数为一个直角三角形的两个直角边,函数会返回斜边的长度。 |
7 double sqrt(double); | 该函数返回参数的平方根。 |
8 int abs(int); | 该函数返回整数的绝对值。 |
9 double fabs(double); | 该函数返回任意一个浮点数的绝对值。 |
10 double floor(double); | 该函数返回一个小于或等于传入参数的最大整数。 |
随机数
在许多情况下,需要生成随机数。关于随机数生成器,有两个相关的函数。一个是 rand(),该函数只返回一个伪随机数。生成随机数之前必须先调用 srand() 函数。
下面是一个关于生成随机数的简单实例。实例中使用了 time() 函数来获取系统时间的秒数,通过调用 rand() 函数来生成随机数
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
int main ()
{
int i,j;
// 设置种子
srand( (unsigned)time( NULL ) );
/* 生成 10 个随机数 */
for( i = 0; i < 10; i++ )
{
// 生成实际的随机数
j= rand();
cout <<"随机数: " << j << endl;
}
return 0;
}
当上面的代码被编译和执行时,它会产生下列结果:
随机数: 1748144778
随机数: 630873888
随机数: 2134540646
随机数: 219404170
随机数: 902129458
随机数: 920445370
随机数: 1319072661
随机数: 257938873
随机数: 1256201101
随机数: 580322989
字符串
由于在数组的末尾存储了空字符,所以字符数组的大小比单词 “Hello” 的字符数多一个。
关于字符串的函数:
序号 函数 | 目的 |
---|---|
1 strcpy(s1, s2); | 复制字符串 s2 到字符串 s1。 |
2 strcat(s1, s2); | 连接字符串 s2 到字符串 s1 的末尾。 |
3 strlen(s1); | 返回字符串 s1 的长度。 |
4 strcmp(s1, s2); | 如果 s1 和 s2 是相同的,则返回 0;如果 s1<s2 则返回值小于 0;如果 s1>s2 则返回值大于 0。 |
5 strchr(s1, ch); | 返回一个指针,指向字符串 s1 中字符 ch 的第一次出现的位置。 |
6 strstr(s1, s2); | 返回一个指针,指向字符串 s1 中字符串 s2 的第一次出现的位置。 |
指针(这是重点)
指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址。就像其他变量或常量一样,您必须在使用指针存储其他变量地址之前,对其进行声明。指针变量声明的一般形式为:
type *var-name;
所有指针的值的实际数据类型,不管是整型、浮点型、字符型,还是其他的数据类型,都是一样的,都是一个代表内存地址的长的十六进制数。不同数据类型的指针之间唯一的不同是,指针所指向的变量或常量的数据类型不同。
作用:链表,动态数组
以后再补充代码例子;
引用
引用变量是一个别名,也就是说,它是某个已存在变量的另一个名字。一旦把引用初始化为某个变量,就可以使用该引用名称或变量名称来指向变量。
C++ 引用 vs 指针
- 引用很容易与指针混淆,它们之间有三个主要的不同:
- 不存在空引用。引用必须连接到一块合法的内存。
- 一旦引用被初始化为一个对象,就不能被指向到另一个对象。指针可以在任何时候指到另一个对象。
- 引用必须在创建时被初始化。指针可以在任何时间被初始化。
创建引用
vartype& 变量 =被引用的变量;
输入输出流
标准错误流(cerr)
预定义的对象 cerr 是 iostream 类的一个实例。cerr 对象附属到标准错误设备,通常也是显示屏,但是 cerr 对象是非缓冲的,且每个流插入到 cerr 都会立即输出。
cerr 也是与流插入运算符 << 结合使用的,如下所示:
#include <iostream>
using namespace std;
int main( )
{
char str[] = "Unable to read....";
cerr << "Error message : " << str << endl;
}
文件读写
本部分转载自(https://www.cnblogs.com/liaocheng/p/4371796.html)
相关的头文件:#include
需要相关的类
fstream提供三种类,实现C++对文件的操作
ofstream:写操作,由ostream引申而来
ifstream:读操作,由istream引申而来
fstream :同时读写操作,由iostream引申而来
文件的类型:文本文件 和 二进制文件
文件读写的步骤:
- 1、包含的头文件:#include
- 2、创建流
- 3、打开文件(文件和流关联)
- 4、读写 (写操作:<<,put( ), write( ) 读操作: >> , get( ),getline( ), read( ))
- 5、关闭文件:把缓冲区数据完整地写入文件, 添加文件结束标志, 切断流对象和外部文件的连接
方法及示例
- 1.文本文件的读写:
方法:
一次性读写若干字符
1)使用运算符<< 和 >>进行读写
功能:
<< 能实现以行为单位写入文件
>> 不能一行为单位读入内存,总是以空格、Tab、回车结束,而是以单词为单位
代码:
函数功能:使用<< ,写入文件一行字符
eg:
#include <fstream>
#include <iostream>
using namespace std;
void main()
{
ofstream OpenFile("file.txt");
if (OpenFile.fail())
{
cout<<"打开文件错误!"<<endl;
exit(0);
}
OpenFile<<"abc def ghi";
OpenFile.close();
system("pause");
}
2)使用运算符<<(写)和getline()进行读写
功能:
<<:以行为单位输入文件
getline():以行为单位 读入内存,能一次读入一行
函数原型:istream &getline( char *buffer, streamsize num );
功能:getline( )函数用于从文件读取num-1个字符到buffer(内存)中,直到下列情况发生时,读取结束:
1):num - 1个字符已经读入
2):碰到一个换行标志
3):碰到一个EOF
eg:
#include <fstream>
#include <iostream>
using namespace std;
void main()
{
const int len=20;
char str[len];
ifstream OpenFile("file.txt");
if (OpenFile.fail())
{
cout<<"打开文件错误!"<<endl;
exit(0);
}
OpenFile.getline(str,20);
cout<<str<<endl;
OpenFile.close();
system("pause");
}
3)一次读写一个字符:
使用get( )和put( )函数
函数声明:istream& get(char &c);
函数功能:使用 get( )函数 把字符1输入到文件
//put()
#include <fstream>
#include <iostream>
using namespace std;
void main()
{
char ch='1';
ofstream OpenFile("file.txt");
if (OpenFile.fail())
{
cout<<"打开文件错误!"<<endl;
exit(0);
}
OpenFile.put(ch);
OpenFile.close();
system("pause");
}
//get()
#include <fstream>
#include <iostream>
using namespace std;
void main()
{
char ch;
ifstream OpenFile("file.txt");
if (OpenFile.fail())
{
cout<<"打开文件错误!"<<endl;
exit(0);
}
OpenFile.get(ch);
cout<<ch;
OpenFile.close();
system("pause");
}
-
2.二进制文件的读写:
1)使用运算符get( ) 和 put( )读写一个字节
功能:get( ) :在文件中读取一个字节到内存
函数原型:ifstream &get(char ch)
put( ) :在内存中写入一个字节到文件
函数原型:ofstream &put(char ch)
代码略。
2)使用read()和write()进行读写
read( ):
功能:从文件中提取 n 个字节数据,写入buf指向的地方中
函数声明:istream & read ( char * buf , int n ) ;
write( ):
功能:把buf指向的内容取n个字节写入文件
函数声明:ostream & ostream :: write ( char * buf , int n ) ;
参数说明:buf表示要写入内存的地址,传参时要取地址。n表示要读入字节的长度
注意:1):该函数遇到空字符时并不停止,因而能够写入完整的类结构
2):第一个参数一个char型指针(指向内存数据的起始地址),与对象结合使用的时候,要在对象地址之前要char做强制类型转换。
//write()
#include <fstream>
#include <iostream>
using namespace std;
void main()
{
char ch[12]="12 3 456 78";
ofstream OpenFile("file.txt");
if (OpenFile.fail())
{
cout<<"打开文件错误!"<<endl;
exit(0);
}
OpenFile.write(ch,12);
OpenFile.close();
system("pause");
}
//read()
void main()
{
char ch[12];
ifstream OpenFile("file.txt");
if (OpenFile.fail())
{
cout<<"打开文件错误!"<<endl;
exit(0);
}
OpenFile.read(ch,12);
cout<<ch;
OpenFile.close();
system("pause");
}
访问控制和继承
派生类可以访问基类中所有的非私有成员。因此基类成员如果不想被派生类的成员函数访问,则应在基类中声明为 private。
我们可以根据访问权限总结出不同的访问类型,如下所示:
访问 | public | protected | private |
---|---|---|---|
同一个类 | yes | yes | yes |
派生类 | yes | yes | no |
外部的类 | yes | no | no |
一个派生类继承了所有的基类方法,但下列情况除外:
基类的构造函数、析构函数和拷贝构造函数。
基类的重载运算符。
基类的友元函数。
多继承
多继承即一个子类可以有多个父类,它继承了多个父类的特性。
C++ 类可以从多个类继承成员,语法如下:
class <派生类名>:<继承方式1><基类名1>,<继承方式2><基类名2>,…
{
<派生类类体>
};
函数重载
在同一个作用域内,可以声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数、类型或者顺序)必须不同。您不能仅通过返回类型的不同来重载函数。
运算符重载
您可以重定义或重载大部分 C++ 内置的运算符。这样,您就能使用自定义类型的运算符。
重载的运算符是带有特殊名称的函数,函数名是由关键字 operator 和其后要重载的运算符符号构成的。与其他函数一样,重载运算符有一个返回类型和一个参数列表。
Box operator+(const Box&, const Box&);
虚函数
虚函数 是在基类中使用关键字 virtual 声明的函数。在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数。
我们想要的是在程序中任意点可以根据所调用的对象类型来选择调用的函数,这种操作被称为动态链接,或后期绑定。
示例:
#include <iostream>
using namespace std;
class Shape {
protected:
int width, height;
public:
Shape( int a=0, int b=0)
{
width = a;
height = b;
}
int area()
{
cout << "Parent class area :" <<endl;
return 0;
}
};
class Rectangle: public Shape{
public:
Rectangle( int a=0, int b=0):Shape(a, b) { }
int area ()
{
cout << "Rectangle class area :" <<endl;
return (width * height);
}
};
class Triangle: public Shape{
public:
Triangle( int a=0, int b=0):Shape(a, b) { }
virtual int area ()
{
cout << "Triangle class area :" <<endl;
return (width * height / 2);
}
};
// 程序的主函数
int main( )
{
Shape *shape;
Rectangle rec(10,7);
Triangle tri(10,5);
// 存储矩形的地址
shape = &rec;
// 调用矩形的求面积函数 area
shape->area();
// 存储三角形的地址
shape = &tri;
// 调用三角形的求面积函数 area
shape->area();
return 0;
}
//result:
Rectangle class area
Triangle class area
预处理器
参数宏
您可以使用 #define 来定义一个带有参数的宏,如下所示:
#include <iostream>
using namespace std;
#define MIN(a,b) (a<b ? a : b)
int main ()
{
int i, j;
i = 100;
j = 30;
cout <<"较小的值为:" << MIN(i, j) << endl;
return 0;
}
//result:较小的值为:30
多线程
创建线程
下面的程序,我们可以用它来创建一个 POSIX 线程:
#include <pthread.h>
pthread_create (thread, attr, start_routine, arg)
在这里,pthread_create 创建一个新的线程,并让它可执行。下面是关于参数的说明:
参数 | 描述 |
---|---|
thread | 指向线程标识符指针。 |
attr | 一个不透明的属性对象,可以被用来设置线程属性。您可以指定线程属性对象,也可以使用默认值 NULL。 |
start_routine | 线程运行函数起始地址,一旦线程被创建就会执行。 |
arg | 运行函数的参数。它必须通过把引用作为指针强制转换为 void 类型进行传递。如果没有传递参数,则使用 NULL。 |
创建线程成功时,函数返回 0,若返回值不为 0 则说明创建线程失败。
终止线程
使用下面的程序,我们可以用它来终止一个 POSIX 线程:
#include <pthread.h>
pthread_exit (status)
示例:
#include <iostream>
// 必须的头文件
#include <pthread.h>
using namespace std;
#define NUM_THREADS 5
// 线程的运行函数
void* say_hello(void* args)
{
cout << "Hello Runoob!" << endl;
return 0;
}
int main()
{
// 定义线程的 id 变量,多个变量使用数组
pthread_t tids[NUM_THREADS];
for(int i = 0; i < NUM_THREADS; ++i)
{
//参数依次是:创建的线程id,线程参数,调用的函数,传入的函数参数
int ret = pthread_create(&tids[i], NULL, say_hello, NULL);
if (ret != 0)
{
cout << "pthread_create error: error_code=" << ret << endl;
}
}
//等各个线程退出后,进程才结束,否则进程强制结束了,线程可能还没反应过来;
pthread_exit(NULL);
}
剩下的关于web以及STL就不在补充了,以上。