C++入门基础笔记
1、C++第一个程序
程序中\n
与endl
相同,endl表示结束流,在流中起做用!
#include <iostream>
using namespace std;
int main()
{
cout << "Hello, world!" << endl;
return 0;
}
2、注释
可以通过#if 0
与#endif
来注释语句通过更改0与1来确定是否使用语句块
3、数据类型
- 修饰符:
signed
有符号unsigned
无符号short
短的long
长的 - 类型:
bool
布尔型char
字符型int
整型float
浮点型double
双浮点void
无wchar_t
宽字符型 - 值范围:
float
单精度其地址为1位符号,8位指数,23位小数。
double
双精度是1位符号,11位指数,52位小数。char
八位字节
typedef 声明
extern
声明变量应放在main()前面,
extern
可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。另外,extern
也可用来进行链接指定。
extern int c;
enumeration 枚举型
enum color { red, green, blue } c;
c = blue;
默认情况下red的值为0,green为1,以此类推但当:
enum color { red, green=5, blue };
这个情况下时red的值为0,green为5,blue为6.
4、全局变量
全局变量放在mian()前面,所以程序都可以访问,在程序中,局部变量和全局变量的名称可以相同,但是在函数内,局部变量的值会覆盖全局变量的值。局部变量被定义时,系统不会对其初始化,您必须自行对其初始化.全局会自动初始化
int
0 char
"\0" float
0 double
0 pointer
NULL
常量
-
整数常量可以带一个后缀,后缀是 U 和 L 的组合,U 表示无符号整数(unsigned),L 表示长整数(long)。
-
浮点常量当使用指数形式表示时, 必须包含小数点、指数,或同时包含两者。带符号的指数是用 e 或 E 引入的。通过使用后缀 f 或 l常量可以分别指定为 float 或 long double
18.46e0 // 18.46
18.46e1 // 184.6
- 字符常量
`\` 转义符
`\a` 警报铃声
`\b` 退格键
`\f` 换页符
`\n` 换行符
`\r` 回车
`\t` 水平制表符
`\v` 垂直制表符
`\ooo` 一到三位的八进制数
`\xhh...` 一个或多个数字的十六进制数
定义常量
#define 预处理器
\#define LENGTH 10
const前缀声明指定类型的常量
常量不能更新
const int LENGTH = 10;
修饰符类型
explicit
构造函数用于防止隐式调用!
存储类
register
存储类 用于定义存储在寄存器中而不是 RAM 中的局部变量。不能对它应用&
static
存储类 指示编译器在程序的生命周期内保持局部变量的存在.
即在函数中static int i = 5;
局部静态变量 重复调用函数时还能再访问iextern
存储类 在子文件中声明已存在一个已定义的变量或函数的引用mutable
存储类 后面讲解thread_local
存储类 声明的变量仅可在它在其上创建的线程上访问.变量在创建线程时创建,并在销毁线程时销毁。 每个线程都有其自己的变量副本。可以与 static 或 extern 合并。仅应用于数据声明和定义,不能用于函数声明或定义。
thread_local int x;
class X
{
static thread_local std::string s;
};
static thread_local std::string X::s;
void foo()
{
thread_local std::vector<int> v;
}
运算符
- 算术运算符
% 取余运算
- 关系运算符
- 逻辑运算符
&& 与(并且) 逻辑与 AND
||(或) 逻辑或 OR
!(非)
- 位运算符
A = 0011 1100 B = 0000 1101
& 二边为真才为真 ,A&B = 0000 1100 位与 AND
| 有一个为真即真 ,A|B = 0011 1101 位或 OR
^ 二边不一样的真 ,A^B = 0011 0001 位异或 XOR
~ 取反相, ~A = 1100 0011
- 赋值运算符
C += A//相当于 C = C + A
C -= A//相当于 C = C - A
C *= A//相当于 C = C * A
C /= A//相当于 C = C / A
C %= A//相当于 C = C % A
C <<= 2//等同于 C = C << 2
C >>= 2//等同于 C = C >> 2
C &= 2//等同于 C = C & 2
C ^= 2//等同于 C = C ^ 2
C |= 2//等同于 C = C | 2
- 杂项运算符
sizeof 返回变量的大小,字节数如sizeof(int),返回4
x = (y < 10) ? 30 : 40; 当Y=10时,X取40 相当于if语句
.
点运算符与->
箭头运算符 箭头操作符是结构体 或者 对象 指针用来访问其对象 或者 对象成员时用的符号比如struct aaa{int a,int b;};class bb{int a;int b';void test()};当我们定义一个结构体变量的时候比如 aaa t; bb t;往往是通过.符号来获得或者访问其中的成员变量 或者函数如 t.a t.b t.test()但是 如果我们定义的是一个结构体指针aaa *t;bb *t那么就需要用箭头符号来访问了t->a t->b t->test()这么讲你明白了吗强制转换运算符 把一种数据类型转换为另一种数据类型。
int(2.2000) 将返回 2。指针运算符 & 返回变量的地址。例如 &a; 将给出变量的实际地址。
指针运算符 * 指向一个变量。例如,*var; 将指向变量 var。
循环
循环类型
- while(表达式){};
- for(初始化,表达式,i++){};
- do{...}while(表达式);
循环控制
- break跳出(中断)循环体
- continue跳出本次循环(不中断)
- goto转移到被标记,(不建议使用)
函数
函数参数
- 传值调用--
oid swap(int x, int y)
调用时swap(a, b);
- 指针调用--
void swap(int *x, int *y)
调用时swap(&a, &b);
- 引用调用--
swap(int &x, int &y)
调用时swap(a, b);
数字
数学运算
double cos(double);
该函数返回弧度角(double 型)的余弦。double sin(double);
该函数返回弧度角(double 型)的正弦。double tan(double);
该函数返回弧度角(double 型)的正切。double log(double);
该函数返回参数的自然对数。double pow(double, double);
假设第一个参数为 x,第二个参数为 y,则该函数返回 x 的 y 次方。double hypot(double, double);
该函数返回两个参数的平方总和的平方根,也就是说,参数为一个直角三角形的两个直角边,函数会返回斜边的长度。double sqrt(double);
该函数返回参数的平方根。int abs(int);
该函数返回整数的绝对值。double fabs(double);
该函数返回任意一个十进制数的绝对值。double floor(double);
该函数返回一个小于或等于传入参数的最大整数。
数组
double balance[] = {1000.0, 2.0, 3.4, 7.0, 50.0};
double salary = balance[9];
int a[3][4] = {{0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11}};//多维数组
指向数组的指针
double *p;
double balance[10];
p = balance;
使用数组名作为常量指针是合法的,反之亦然。因此,*(balance + 4)
是一种访问 balance[4]
数据的合法方式。一旦您把第一个元素的地址存储在 p
中,您就可以使用 *p
、*(p+1)
、*(p+2)
等来访问数组元素。
传递数组给函数
从函数返回数组
C++ 不允许返回一个完整的数组作为函数的参数。但是,您可以通过指定不带索引的数组名来返回一个指向数组的指针。如果您想要从函数返回一个一维数组,您必须声明一个返回指针的函数,如下:
\#include <iostream>
\#include <cstdlib>
\#include <ctime>
using namespace std;
// 要生成和返回随机数的函数
int * getRandom( )
{
static int r[10];
// 设置种子
srand( (unsigned)time( NULL ) );
for (int i = 0; i < 10; ++i)
{
r[i] = rand();
cout << r[i] << endl;
}
return r;
}
// 要调用上面定义函数的主函数
int main ()
{
// 一个指向整数的指针
int *p;
p = getRandom();
for ( int i = 0; i < 10; i++ )
{
cout << "*(p + " << i << ") : ";
cout << *(p + i) << endl;
}
return 0;
}
字符串
字符
char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};//字符组
cout << greeting << endl; //输出
strcpy(s1, s2);
复制字符串 s2 到字符串 s1。strcat(s1, s2);
连接字符串 s2 到字符串 s1 的末尾。strlen(s1);
返回字符串 s1 的长度。strcmp(s1, s2);
如果 s1 和 s2 是相同的,则返回 0;如果 s1<s2 则返回值小于 0;如果 s1>s2 则返回值大于 0。strchr(s1, ch);
返回一个指针,指向字符串 s1 中字符 ch 的第一次出现的位置。strstr(s1, s2);
返回一个指针,指向字符串 s1 中字符串 s2 的第一次出现的位置。
String类
string str1 = "Hello";
str1.size();//返回长度
指针
指针可以理解为是一个变量,但这变量只存储地址信息,地址
int var = 20;// 实际变量的声明
int *ip;// 指针变量的声明
ip = &var;// 在指针变量中存储 var 的地址
空指针
int *ptr = NULL;
空指针,其地址值为0,空指针中不允许访问地址为 0 的内存,
所以cout <<"ptr的值" <<*ptr;
会报错,应先if(ptr)
判断
指针数组
\#include <iostream>
using namespace std;
const int MAX = 3;
int main ()
{
int var[MAX] = {10, 100, 200};
int *ptr[MAX]; //指针数组
for (int i = 0; i < MAX; i++)
{
ptr[i] = &var[i]; // 赋值为整数的地址
}
for (int i = 0; i < MAX; i++)
{
cout << "Value of var[" << i << "] = ";
cout << *ptr[i] << endl;
}
return 0;
}
指向指针的指针(多级间接寻址)
int var;
int *ptr;
int **pptr;
var = 3000;
ptr = &var;// 获取 var 的地址
pptr = &ptr;// 使用运算符 & 获取 ptr 的地址
传递指针给函数
getSeconds( &sec );//调用时
void getSeconds(unsigned long *par)
{
// 获取当前的秒数
*par = time( NULL );
return;
}
getAverage( balance, 5 );
double getAverage(int *arr, int size)
{
//...
}
从函数返回指针
C++ 不支持在函数外返回局部变量的地址,除非定义局部变量为 static 变量。
int * myFunction()
{
}
//调用
int *p;
p = getRandom();
引用
其与直接使用参数的区别在于,不用开辟一块内存,进行赋值拷贝动作。(可以理解这是一个另名)
把引用作为参数
void swap(int& x, int& y);
int main ()
{
int a = 100;
int b = 200;
swap(a, b);// 调用函数来交换值
return 0;
}
void swap(int& x, int& y)
{
int temp;
temp = x; /* 保存地址 x 的值 */
x = y; /* 把 y 赋值给 x */
y = temp; /* 把 x 赋值给 y */
return;
}
把引用作为返回值
double vals[] = {10.1, 12.6, 33.1, 24.1, 50.0};
double& setValues( int i )
{
return vals[i]; // 返回第 i 个元素的引用
}
int main ()
{
setValues(1) = 20.23; // 改变第 2 个元素
setValues(3) = 70.8; // 改变第 4 个元素
}
注意:1.不能返回局部变量的引用。2.不能返回函数内部new分配的内存的引用 3.可以返回类成员的引用,但最好是const。
日期与时间
程序中引用 <ctime>
头文件。
struct tm { //结构体
int tm_sec; // 秒,正常范围从 0 到 59,但允许至 61
int tm_min; // 分,范围从 0 到 59
int tm_hour; // 小时,范围从 0 到 23
int tm_mday; // 一月中的第几天,范围从 1 到 31
int tm_mon; // 月,范围从 0 到 11
int tm_year; // 自 1900 年起的年数
int tm_wday; // 一周中的第几天,范围从 0 到 6,从星期日算起
int tm_yday; // 一年中的第几天,范围从 0 到 365,从 1 月 1 日算起
int tm_isdst; // 夏令时
}
示例
\#include <stdio.h>
\#include <time.h>
int main ()
{
clock_t start_t, end_t;
double total_t;
start_t = clock();//clock_t clock(void)返回程序执行起(一般为程序的开头)处理器时钟所使用的时间
time_t rawtime;
struct tm *info; //结构体tm
char buffer[80];
time( &rawtime );//返回系统的当前自 1970 年 1 月 1 日以来经过的秒数
info = localtime( &rawtime );//使用 timer 的值来填充 tm 结构
printf("当前的本地时间和日期:%s", asctime(info));
end_t = clock();
total_t = (double)(end_t - start_t) / CLOCKS_PER_SEC;//CLOCKS_PER_SEC是标准c的time.h头函数中宏定义的一个常数,表示一秒钟内CPU运行的时钟周期数,用于将clock()函数的结果转化为以秒为单位的量
printf("CPU 占用的总时间:%f\n", total_t );
return(0);
}
基本输入输出
- cout 输出 cout <<"test"<<endl;
- cin 输入 cin >> name;
- cerr 错误流 cerr << "test" << endl;
- clog 日志流 clog << "test" << endl;
数据结构
strcpy(str1,str2);把str2的字符串数据复制到str1中!
指向结构的指针
printBook( &Book1 );//main调用
void printBook( struct Books *book )
{
cout << "书标题 : " << book->title <<endl;
cout << "书作者 : " << book->author <<endl;
cout << "书类目 : " << book->subject <<endl;
cout << "书 ID : " << book->book_id <<endl;
}
类&对象
类定义
\#include <iostream>
using namespace std;
class Box
{
public:
double length; // 盒子的长度
double breadth; // 盒子的宽度
double height; // 盒子的高度
double getVolume(void);// 返回体积
};
double Box::getVolume(void) //范围解析运算符::定义该函数
{
return length * breadth * height;
}
int main()
{
Box Box1;
double volume = 0.0;// 用于存储体积
Box1.length=6;
Box1.breadth=7;
Box1.height=5;
volume = Box1.getVolume();
cout << "Box1 的体积:" << volume <<endl;
return 0;
}
}
继承
格式
class Rectangle: public Shape{}
Shape为基类
多继承
class <派生类名>:<继承方式1><基类名1>,<继承方式2><基类名2>,…{<派生类类体>};
虚继承
格式:class 类名: virtual 继承方式 父类名
- 举例来说:假如类A和类B是由类X继承而来(非虚继承且假设类X包含一些成员),且类C同时继承了类A和B,那么C就会拥有两套和X相关的成员(可分别独立访问,一般要用适当的消歧义修饰符)。但是如果类A虚继承自类X,那么C将会只包含一组类X的成员数据。
重载运算符和重载函数
重载函数
class printData
{
public:
void print(int i) {
cout << "整数为: " << i << endl;
}
void print(double f) {
cout << "浮点数为: " << f << endl;
}
};
运算符重载
// 重载 + 运算符,用于把两个 Box 对象相加
Box operator+(const Box& b)
{
Box box;
box.length = this->length + b.length;
return box; //返回box
}
// 重载小于运算符( < )
bool operator <(const Distance& d)
{
if(feet < d.feet)
{
return true;
}
if(feet == d.feet && inches < d.inches)
{
return true;
}
return false;
}
//重载输出
friend ostream &operator<<( ostream &output,
const Distance &D )
{
output << "F : " << D.feet << " I : " << D.inches;
return output;
}
//重载输入
friend istream &operator>>( istream &input, Distance &D )
{
input >> D.feet >> D.inches;
return input;
}
其它重载请查看 菜鸟教程