C++复习整理
-
允许用0B或0b作为前缀表示二进制数字(0B10010=37)
-
八进制十进制每3位添加一个’(分隔符),二进制十六进制每4位添加一个
-
进制转换:(1条消息) 计算机基础进制转换(二进制、八进制、十进制、十六进制)_戴翔的技术博客-CSDN博客_计算机进制
-
‘\b’的作用:输出到7时遇到3个\b,光标向前移动三个到3后面,输出89覆盖后面的45(如果光标遇到\n则停止移动)
#include <stdio.h> int main(void) { printf("1234567\b\b\b\b89"); //输出1238967 return 0; }
-
自定义字面值(后缀必须以_开头)
#include<iostream> using namespace std; typedef unsigned long long ull; ull operator""_km(ull n) { return n * 1000000; } int main() //输出disetace is:12000000mm { cout << "disetace is:" << 12_km << "mm" << endl; return 0; }
-
cin.get()具备读取空白字符,以及包含空白字符的字符串的能力,会接受缓存区的字符,如果上一行有\n则会被接受,程序出现bug。也可以暂停程序,等待用户输入任意键继续。
-
cin.getline()函数也具有类似于cin.get()的作用可以接收空白字符,但是遇到换行符会终止输入,并不会影响输出结果。超过规定字符数字时需要用cin.clear()函数重新打开输入流。再次正确使用cin.getline()输出后面的字符。
-
cin.gcount()返回上一次cin输入的字符个数(针对get,getline,read)
-
cin.ignore()舍弃缓冲区中的字符,cin.ignore(100,\n )忽略缓冲区中前100个字符,遇到\n停止。
-
boolalpha
引用(给变量起别名):数据类型 &别名=原名
-
引用必须初始化:int &b;(×)
-
引用一经初始化便不可修改,即不能当作另一个数据的别名
-
不要返回局部变量的引用
-
函数的调用可以作为左值
#include<iostream> using namespace std; //test01为返回局部变量的引用 int& test01() { int a = 10; return a; } //test02:如果函数返回值是引用,则该函数的调用可以作为左值使用 int& test02() { static int a = 10; //static:将a存放至全局区,不会被释放 return a; } int main() { int& ref01 =test01(); cout << ref01 << endl; cout << ref01 << endl; //此时a已经被释放,无法显示正确的结果 int& ref02 = test02(); cout << ref02 << endl; cout << ref02 << endl; //static:作为全局变量后,a的值不再发生更改 test02() = 100; //相当于a=100 cout << ref02 << endl; cout << ref02 << endl; return 0; }
-
引用的本质:指针常量
int &ref=10 //error const int &ref=10 //true 但是ref只读不可修改
-
const修饰形参防止误操作
#include<iostream> using namespace std; void showVal(int &val) //只要求打印不改变原参数则可以改成showVal(const int &val) { val = 100; //当引用作为形参时可以在函数中进行修改,此时主函数中的a也会发生改变 cout << "val=" << val << endl; } int main() { int a = 10; showVal(a); cout << "a=" << a << endl; //输出val=100,a=100 return 0; }
函数
-
函数可以设置默认参数
#include<iostream> using namespace std; //int add(int a=10,b=10,c=10);如果函数声明设定了默认值,下方函数的实现就不能设置 int add(int a, int b=20, int c=30) //给b设定默认值后,b后面的数都必须有默认值 { return a + b + c; } int main() { cout<<add(10, 30); //自己传入的b是30,但是函数参数为20此时取调用时的数 return 0; //输出70 }
-
占位参数
#include<iostream> using namespace std; void func(int a, int) //两种方式都可,但是此后只有第一个数据可以使用 { //可以改为void func(int a,int =1;)下面第二个就不必再传(默认参数) cout << "占位参数" << endl; } int main() { func(1, 1);//必须传入数据 return 0; }
-
函数重载:可以让函数名相同,提高复用性
-
满足条件
- 在同一个作用域下
- 函数名称相同
- 函数参数 类型不同 或者 个数不同 或者顺序不同
-
函数返回值不可以作为重载的条件
int func(int a,double b); void func(int a,double b); //error
-
函数引用可以作为重载的条件使用
void func(int &a); //int a;func(a) void func(const &a);//func(10)
-
函数重载遇到默认参数时
void func(int a ,int b=10); void func(int a); //error
-
类
-
三种访问权限
- 公共权限 public:类内类外都可以访问
- 保护权限protected:类内和子类可以访问,类外不可以
- 私有权限private:类内可以访问
-
c++中strucct和class唯一的区别:struct默认权限为公共,class默认权限为私有
-
set、get访问器:(还可以判断用户输入数字的有效性)
#include<iostream>
using namespace std;
class Stdent
{
public:
void setName(string name) //设置姓名
{
s_name = name;
}
string getName() //获取姓名
{
return s_name;
}
private:
string s_name;
};
int main()
{
Stdent std;
std.setName("th");
cout<<"姓名:"<<std.getName()<<endl;
}
- 父类中所有非静态成员属性子类都可以继承。私有成员子类也可以继承,但是被编译器隐藏了访问不到。
- 构造函数:主要作用于创建对象时为对象的成员属性赋值,构造函数由编译器自动调用,无需手动调用。
- 没有返回值,也不写void
- 函数名称与类名相同
- 构造函数可以有参数,因此可以发生重载
- 在调用对象时会自动调用构造,且智慧调用一次
- 析构函数:对象消亡时,自动被调用,用来释放对象占用的空间
- (在main函数中可能看不到析构函数的调用,因为窗口关闭构造函数销毁时才会调用)
- 名字与类名相同
- 在前面需要加上"~"
- 无参数,无返回值(不可以发生重载)
- 一个类最多只有一个析构函数
- 不显示定义析构函数会调用默认析构函数(缺省析构函数)
- 拷贝函数调用时机:
- 使用一个已经创建完毕的对象来初始化一个新对象
- 值传递的方式给函数参数传值
- 以值方式返回局部对象
- 用户定义有参构造函数时,c++不再提供默认无参构造,但是会提供默认拷贝函数
- 用户只提供拷贝函数时,c++不再提供默认无参构造
- 匿名对象:构造一个有返回值的构造函数后,
类名(参数);
,构造函数使用之后将会立即使用虚构函数。 - 浅拷贝:简单的赋值拷贝操作
- 堆区的内存会重复释放
- 深拷贝:在堆区重新申请空间,进行拷贝操作。
- 静态成员变量
- 所有对象共享同一份数据
- 在编译阶段分配内存
- 类内声明,类外初始化
class Person
{
public:
static int m_A; //类内声明
};
int Person::m_A=100; //类外初始化
-
静态成员变量仍然有访问权限,如果设置在私有权限下,类外就不能访问
-
因为静态变量不属于任何对象,所有对象共享这一份所有有两种访问方式
// 1 Person p; cout<<p.m_A<<endl; // 2 cout<<Person::m_A<<endl;
-
静态成员函数
- 所有对象共享同一个函数
- 静态成员函数只能访问静态成员变量
-
空类占一个字节
-
this指针是隐含在每一个非静态成员函数内的一种指针:指向 被调用的成员函数 所属的对象
-
解决名称冲突
-
返回对象本身用*this
-
#include<iostream> using namespace std; class Person { public: Person(int age) { this->age = age; } Person& personAdd(Person& p) //返回本体时用引用的方式返回(重点) { this->age += p.age; return *this; } int age; }; int main() { Person p = 10; Person p1 = 10; p1.personAdd(p).personAdd(p).personAdd(p); //此时能够重复调用此函数(链式编程思想) cout << "p1的年龄是" << p1.age << endl; return 0; }
-
-
空指针可以访问成员函数,但是访问涉及this->的成员函数时this指针为空,会报错
void showPersonAge() { if(this==NULL) { return ; //这样处理 } cout<<"age = "<<this->m_Age<<endl;//this指针传入为空 }
-
const修饰成员函数(常函数)
-
常对象只能调用常函数,因为普通成员函数可以修改属性
-
友元函数:让一个函数或者类访问另一个类中的私有成员
- 全局函数做友元
- 类做友元
- 成员函数做友元(友元的三种实现)
-
只能利用全局函数重载左移运算符(成员函数无法实现cout在左边输出)
-
运算符重载
#include<iostream> using namespace std; class Person { friend ostream& operator<<(ostream& cout, Person& p); public: Person operator+(Person &p) { Person tep(0,0); tep.m_A=this->m_A + p.m_A; tep.m_B=this->m_B + p.m_B; return tep; } Person(int a,int b) { this->m_A = a; this->m_B = b; } private: int m_A; int m_B; }; //左移运算符 ostream& operator<<(ostream&cout, Person& p) { cout << p.m_A << endl; cout << p.m_B << endl; return cout; } int main() { Person p1(10, 20); Person p2(0,0); p2 = p1 + p1; cout << p2 << endl; return 0; }
-
继承中先构造父类再构造子类,析构顺序相反
-
子类和父类中出现同名的成员时直接访问是子类的成员,如果要访问父类需要添加作用域:son.data(子类) son.dad::data(父类)
-
子类不会继承父类的构造函数,只能调用
-
动态多态满足条件:
- 有继承关系
- 子类重写父类的虚函数(函数重载)
-
动态多态使用条件:父类指针或引用指向子类对象