c++笔记

261 阅读3分钟

const

常量指针const int *p = &a; 指针的指向可以修改,但指针指向的值不能修改。

指针常量int * const p =&a;指针的指向不可以改,指针指向的值可以改。

const即修饰指针又修饰常量 const int * const p =&a; 指针的指向和指针指向的值都不可以修改。

* 与 ->

struct Student{
	string name;
    int age;
    int score;
} liming;

student *p = &liming;
liming.name == p->name;  //√
void printStudent(student *p){     //地址传递  指针接收
	cout << p->name << endl;
}
int main(){
	printStudent(&liming);
}

四个区

运行前

  • 代码区: 存放机器指令,只读,共享
  • 全局区: 全局变量,静态变量(static,全局/局部),字符串常量(全局/局部)。操作系统管理其生命周期 运行时
  • 栈区: 不要返回局部变量的地址
  • 堆区:
int* p = new int(10);  
delete p;

int* arr = new int[10];
delete[] arr;

引用

  • 给变量起别名
int a = 10; 
int &b = a;  

注:必须初始化,初始化后不可改变。

  • 引用做参数
//swap    引用达到交换的目的
void swap(int &a, int &b){
	int temp = a;
    a = b;
    b = temp;
}
int a = 10;
int b = 20;
swap(a,b);
  • 引用做函数返回值 不要返回局部变量的引用;函数的调用可以作为左值
int& test(){
	static int a = 10;  //static  变量变为全局
    return a;
}
int main(){
	int &ref = test();
	cout<<ref<<endl;   //10
    test() = 1000;
    cout<<ref<<endl;  //1000
}

本质是指针常量。

int a = 1;
int &ref = a;

int * const ref = &a;   //相当于这个
const int & temp =10;   //合法 不允许修改 相当于,int temp = 10; const int & ref =temp;

函数

默认参数

  • 默认参数 放最后,从默认参数开始到右都得有
int sum(int a,int b = 10){   
	return a+b;
}
sum(10);   //结果20
  • 声明和实现 只能有一个有默认参数,避免二义性 函数重载

返回值不同,不可以作为函数重载的条件。

void func(const int &a){  //1
}
void func(int &a){    //2
}
int a = 10;
func(a);  //使用2函数
func(10);   //使用1函数

对象

封装 继承 多态

struct 与 class

struct C1{
	int m_1;
}
class C2{
	int m_2;
}
int main(){
    C1 c1;
    C2 c2;

    c1.m_1 = 1;   // √ struct内默认是公共的
    c2.m_2 = 1;   // × class内默认是公共的
}

构造函数

  • Person p2(); //×
  • 匿名对象 构造后会执行析构
  • 不用拷贝构造函数生成匿名对象,若有p3,则在进行Person(p3)等价于Person p3,重复定义
  • Person p4 = 10;相当于Person p4 = Person(10); 普通构造
  • Person p5 = p4;相当于Person p5 = Person(p4); 拷贝构造 初始化列表
class Person{
public:
	Person(int a,int b,int c) :m_A(a),m_B(b),m_C(c){ 
    }
    int m_A;
    int m_B;
    int m_C;
}

静态成员变量

  • 共享同一份
  • 编译阶段分配内存
  • 类内声明 类外初始化 静态成员函数
  • 共享1个函数
  • 只能访问静态成员变量 const修饰成员函数
  • 常函数 成员函数后加const,常函数内不可以修改成员属性,若想修改成员属性加mutable
  • 常对象 只能调用常函数

友元

friend

  • 全局函数做友元
  • 类做友元
  • 成员函数做友元 运算符重载
Person operator+ (Person &p1,Person &p2){
	... ...
}  //重载+
Person p3 = p1 + p2;

继承

  • 公共继承 保护继承 私有继承
  • 开发人员命令提示工具查看对象模型 cl /d1 reportSingleClassLayout类名 文件名
  • 需继承解决菱形继承的问题 多态
  • 静态多态 函数重载,运算符重载--->早绑定
  • 动态多态 派生类+虚函数实现 ---->晚绑定,父类的指针或者引用指向子类的对象
  • 纯虚函数 父类虚函数无实际意义,使用纯虚函数。
virtual void speak() = 0;
  • 抽象类 有纯虚函数的就是,无法实例化对象。子类必须重写纯虚函数,否则无法实例化 析构与纯析构
  • 多态使用时候,若子类中有属性开辟到堆区,父类指针在释放时,无法调用子类的析构代码,将父类的析构函数改为虚析构或者纯虚析构
virtual ~Animal(){    //虚析构
	cout<<"Animal析构函数调用"<<endl;
}

virtual ~Animal() = 0;  //纯虚析构,也属于抽象类,无法实例化对象  类内声明  类外实现  与虚析构不共存

文件

<fstream>

两种

  • 文本文件
  • 二进制文件 三操作
  • ofstream
  • ifstream
  • fstream

模板

函数模板

template<typename T> 

template 声明创建模板; typename 表明其后的符号是一种数据类型,也可以用class代替; T 通用的数据类型。

template<typename T> 
void mySwap(T &a,T &b){
	T temp =a;
    a=b;
    b=temp;
}
int a = 10;
int b= 20;
mySwap(a,b);         //1.自动类型推导,必须推导出一致的数据类型才可以使用
mySwap<int>(a,b);    //2.显示指定类型

模板必须确定T的数据类型才可以使用

普通函数 vs 函数模板

  • 隐式类型转换: 1.普通函数可以隐式转换 2.函数模板中的显示指定类型可以发生隐式子类型类型转换 3.函数模板中的自动类型推导不会发生隐式类型转换
  • 调用规则: 1.优先调用普通函数 2.通过空模板参数列表,强制调用 myprint<>(a,b); 3.函数模板也可以重载 4.函数模板可以产生更好的匹配(普通函数需要隐式类型转换),则调用函数模板

类模板

template<class NameType,class AgeType>
class Person
{
public:
	Person(NameType name, AgeType age){
    	this->mName = name;
        this->mAge = age;
    }
}

  • 类模板没有制定类型推导
  • 类模板在模板参数列表中 可以有默认参数
  • 类模板中的成员函数在创建的时候调用,普通类中的成员函数在一开始即可创建
  • 做函数参数:1.指定传入类型 2.参数模板化(确定参数数据类型用 typeid(T1)) 3.整个类模板化
  • 类模板的继承
template<class T>
class Base
{
	T m;
}
class Son:public Base<int>    //必须要知道父类的T类型,才能继承给子类
{
	
};
template<class T>
class Base
{
	T m;
}

template<class T1,class T2>
class Son2:public Base<T2>
{
	T1 obj;	
};

void test(){
	Son2<int,char>S2;
}
  • 模板类 构造函数,成员函数 类外实现
template<class T1,class T2>
class Person{
public:
	Person(T1 name, T2 age);
    void showPerson();
}


template<class T1 , class T2>
Person<T1,T2>::Person(T1 name,T2 age){
	this->m_Name = name;
    this->m_Age = age;
}

temlate<class T1,class T2>
void Person<T1,T2>::showPerson(){

}
  • 分文件编写 1.直接包含.cpp文件 2.将声明和实现写在同一个文件中,并更改后缀为hpp(约定的名称)
  • 类模板与友元 1.全局函数类内实现 2.全局函数类外实现

STL

标准模板库

从广义上分为 容器 算法 迭代器

容器和算法之间通过迭代器进行无缝衔接

六大组件:容器 算法 迭代器 仿函数 适配器 空间配置器

容器:序列式容器,关联式容器。 vector string deque list set map

算法:质变算法,非质变算法

迭代器:类似于指针