day1
{
C++ 的函数可以带默认参数:
默认参数设置规则:
1、只能在函数声明时,设置默认参数,定义时不能写默认值
2、默认参数只能从参数列表的最右边开始,依次往左赋值
注意:
1、默认参数结合函数重载,在调用时,容易参数歧义(二义性)。
2、如果要对引用类型的形参 赋初值,那么必须使用已经存在的 全局变量
C++ 中的函数重载,函数名相同,但是参数列表必须不同
1、参数个数不同
2、参数个数相同,但是类型不同
inline int add(int , int ); //声明一个内联函数
内联函数,只在声明时使用 inline 说明。
注意:
1、频繁使用的函数
2、函数代码语句很少(5句)
3、函数代码语句简单,没有控制语句(循环语句,switch)
目的:
提升程序运行时的效率,缺点就是 目标程序体积变大
}
day2
{
OOP思想:
{
面向对象编程思想。
抽象:声明定义一个类,概括出一类对象的公共性质。
数据抽象:设计成员变量
代码抽象:设置成员函数
封装:将数据成员和成员函数结合在一起,形成一个整体,就是类体部分。实现细节隐藏
继承:扩展已存在的代码,目的是代码重用
多态:接口重用。
}
类:优先开辟成员变量
{
代码角度:用户自定义的数据类型,由class进行说明
抽象角度:对象的类型,是一批对象的共性和特征,是对象的抽象概括。
对象:
代码角度:就是一个变量
抽象角度:具备行为和属性的事物。一切皆为对象,也是类的具体实例。
特点:
类的默认权限是private私有的。
与结构体区别:定义类变量和类指针时,省略class;(使用时数据类型省略class,用类名表示数据类型)
需引入成员函数:实现数据的隐藏和封装
数据类型 类名::函数名(参数){};
类的成员函数都有一个特殊的指针this:指向访问当前成员函数的对象。
成员变量的作用域:
整个类的作用域(类域):类的所有成员函数的函数体区域。
默认生成:定义类时
默认生成构造函数、析构函数、复制构造、赋值运算、地址运算。
注意:
无参数的构造函数显示说明之后,带参数的构造函数还会自动生成;
带参数的构造函数显示说明之后,无参数的构造函数将不会自动生成
构造函数:初始化对象时系统自动调用。
目的:初始化对象。
特点:默认构造函数没有显示说明时会自动生成
没有数据类型(没有返回值)
只能在定义对象时被系统自动调用
构造函数函数名与类名一致
构造函数可以
构造函数可以有默认参数
构造函数是类的特殊成员函数
一般声明在public区域,也可以声明在protect和private区域(限制函数);
拷贝构造:将一个对象复制给另一个相同类型的对象。
类名 (类名& obj){} //&是引用符号 如果不写& 调用该函数时给obj初始化,会陷入死循环
浅拷贝:this->name=obj.name;
同类型的两个对象的成员指针指向同一个堆空间,两个指针会相互干扰
深拷贝:this->name=new char[strlen(obj.name)+1];
重新开辟空间,复制内容,两个指针不会相互影响。
析构函数:回收对象占用的资源
~ 类名(){};
不能被重载
没有数据类型,没有参数。
对象生命周期结束时(程序结束),系统自动调用;
对象指针遇见delete时,系统自动调用;
}
}
day3
{
static关键字:
{
静态成员变量:
在整个类域可见,与具体对象无关,但要注意私有成员变量不能直接用类名.访问;
可以用于同类型的不同对象之间的数据传递。
必须在类体之外定义初始化。//数据类型 类名::变量=初值
静态成员函数:
与具体对象无关//不能用this指针访问成员。通过类体名::变量名访问,或直接访问静态变量。
类体内声明 static 返回值 函数名(参数)
类体外定义时,不能有static修饰
不能访问类的非静态成员
}
const关键字
{
修饰成员变量:
表示只读,必须在构造函数的参数初始化列表中赋初值。
参数初始化列表语法://参数初始化列表在构造函数外部,不能使用this指针。
定义时写,不能在声明时写。
类名(形参):成员变量(形参1),成员变量2(形参2)....{};
包含const成员变量的类的所有构造函数都必须写出初始化列表//包括无参数的构造函数。
类名::类名():变量(常数){}
修饰成员函数:
有this指针
在声明和定义时都必须加const
声明:返回值 函数名(参数)const;
定义:返回值 类名::函数名(参数)const{}
不能通过该函数修改任何成员数据,只能访问;
修饰对象:
const 类名 变量名
只能访问const成员函数,不能访问非const成员函数,可以访问非const成员变量(该变量是公有的)
}
友元:提高了效率但是破坏了类的隐藏和封装(不会被private和protected限制)
{
友元函数:
friend 数据类型 函数名(参数);//声明友元函数,表示该函数不再是成员函数,不能使用this指针
没有权限限定,可以访问私有数据。对象.变量名 或者 类名::变量名(静态变量)
调用时不能通过对象名.函数名调用。只能像普通函数一样直接通过函数名调用
友元函数如果没有类类型作为形参,那么必须在类的外部进行定义(声明必须在类体中)。否则声明定义都可以在类体中。
友元类:
在A类体内声明friend class B;那么在B类的所有成员函数中 都将打破A类的权限。
没有传递性和交换性。//友元关系的共性
友元成员函数:
}
}
day4
{
运算符重载:重新定义运算符,赋予已有运算符新的功能。
运算符重载函数:成员函数或友元函数 普通函数
返回值类型 operator 运算符()//函数名是operrator 运算符
不能被重载的运算符:“.”、 ?sizeof “?:” 作用域“::”
“=”“&”不必重载
成员运算符重载函数
函数体中有一个this指针指向第一个操作数。重载函数的形参个数=操作数-1;
注:单目运算符b++、b--的重载:需要传一个形参占位
友元运算符重载函数
没有this指针,形参个数等于操作数
除了b++、b--
仿函数:对()运算符的重载,只能用成员函数重载,不能用友元函数。//参数个数不固定
匿名对象:
返回类的成员变量,并且期待返回之后能够改变成员变量的数值,则返回引用类型
}
day5
{
模板
{
参数多态化的工具,让函数或类具备通用性。
目的:让程序员编写与类型无关的程序,是泛型编程的基础
分类:
函数模板:仅针对函数参数类型、返回值不同,功能相同的函数。
类模板:仅针对数据成员和成员函数类型不同的类。
格式:template<class T>
template:关键字,说明是一个模板
T:类型模板形参,用来替换数据类型;可以有默认参数(32位系统编译时,必须-std=c++0X)
默认值无意义
class等价于typename
显示调用:函数名<>(参数)//自动匹配数据类型
函数名<数据类型>(参数)//手动传入参数类型个数与实参个数不一致时,从左向右赋值,其余的自动匹配类型
隐式调用:函数名(参数)//有非类型模板参数时,不能隐式调用
非类型模板形参:int、指针、引用//可以有默认值 注:默认值必须写在声明时
目的:让模板中的常数具备灵活性,例如开辟数组空间大小
类模板 数据类型,使用时 类名<类型形参>
在定义对象时不能隐式说明,不能自动匹配类型//类名<数据类型> 对象名(初始值);
类模板里面的所有成员函数都是函数模板,调用成员函数时不能显示调用,只能像调用普通函数那样调用
成员函数在类体外定义:
template <class B>
B 类名<B>::函数名(参数)
作用域访问符前必须是 类名<类型形参>
类模板:类型模板形参可以有默认值。
调用时<>里可以省略参数类型形参
}
}
day6
{
继承:一个新类从已有的类那里获得其已有的特性。
类的派生:已有的类产生一个新类
派生类继承了基类的所有数据成员大部分成员函数(不继承构造和析构函数)
基类:继承当中已存在的类
c++代码重用:类库、类的继承、多态、泛型编程。
最远派生类:最外层的派生类
class 子类名 :访问权限限定符 父类名
private:(默认继承方式)
基类的public变private protected变private //不能向上隐式转换
派生类内部可以访问基类公有和保护成员
派生类的外部不能基类访问任何成员
protected:基类的 public\private成员变成protected成员 //只能在派生类中向上隐式转换
public:继承过来的成员权限不变
在子类外部可以通过对象名.访问公有成员,不可以访问protected和private成员
在子类内部,可以访问父类公有成员和受保护成员,不能直接访问父类私有成员
子类会隐藏父类同名的成员//即 子类定义与父类同名的成员时,子类和父类的该成员都是存在的
要访问父类的同名成员,必须使用父类名::成员名
继承时,构造顺序:先基类构造,再派生类构造
析构顺序:先派生类析构,再基类析构
包含对象成员的派生类和基类构造顺序
先基类构造,再对象成员构造,最后派生类构造
析构与构造顺序相反
派生类构造函数参数化初始列表中,隐式调用基类默认构造(无参数的构造函数)
如果基类出现带参数的构造函数,必须在派生类的构造函数参数初始化列表中,显式调用基类带参数构造函数
如果派生类对象成员的构造带参数,必须在派生类的构造函数参数初始化列表中,为这个对象成员赋初值
默认向上隐式转换:
将派生类对象赋值给基类对象时,将派生类转换成基类类型。//派生类将丢弃自身的数据部分
向下转换是不被允许的,不允许将大范围赋值给小范围
多重继承
{
一个派生类有多个基类。
多重继承的名字二义性:继承的多个基类中有同名的成员数据
继承了多个名字相同的成员变量或成员函数,作用域访问符解决
obj.父类名::成员数据
路径二义性:继承的多个基类有相同的父类
obj.父类名::成员数据
virtual关键字:继承时在:后面加virtual关键字。设置虚基类(虚继承共同的基类)
}
}
day7
{
多态:
{
一个接口多种方法。 //接口重用
实质:程序在运行时才决定调用的函数,也是面向对象编程的核心概念。
多态性:将接口与实现进行分离,也就是实现共同的方法,但是因为个体差异性,而采取不同的策略
虚函数:virtual修饰的成员函数
必须是类的成员函数
类的静态成员函数不能定义为虚函数,
构造函数不能定义为虚函数,但是析构函数可以被定义为虚函数(遇见delete)
函数声明是使用virtual关键字,定义时不用
基类有虚拟函数,那么派生类中的同名函数(函数名,参数,返回值相同)自动成为虚函数
}
动态联编:
多态和虚函数。
引入虚函数表
运行时才决定调用哪个函数
静态联编:
类的大小:
空类占一个字节。//占位符
按照最大数据类型进行数据对齐。
虚函数存在(不论几个),虚函数表占4字节
函数在没有调用的时候不占空间
static修饰的成员数据不算入类的大小
抽象基类:不能有具体实例(对象);不能有静态成员
包含纯虚函数的类
纯虚函数:virtual 函数名()=0;
派生类应该实现基类的所有方法
虚基类:
虚析构函数:
解决资源回收不完整问题//基类指针指向堆区派生类对象首地址,delete时不会调用派生类的析构函数
抽象类的析构函数可以设计成纯虚函数:必须定义,在类体外定义
限制构造函数
构造函数放在非public区域
explicit关键字。不允许定义对象时隐式转换
}
day8
{
异常:容错机制,错误处理思想
保障程序运行稳定性和健壮性。
基本思想:让一个函数在发生自己不能处理的错误时,抛出一个异常(类对象),让他的调用者能够处理这个问题
c++中默认每一个函数都会抛出异常,但不会指定抛出的异常类型
所有函数设计者应该在声明和定义时都需要显示说明抛出的异常类型
//在函数参数列表后面写throw(异常类型)
//如果不会抛出异常就写throw() 64位写noexcept;如果内部强行抛出异常,程序终止
bad_alloc:new、new[],请求内存失败
out_of_range:超出有效范围
invalid_argument:无效参数
转换函数:
operater 需要转换成的类型名(){}
实质:运算符重载,重载的不是运算符,而是类名或者基本数据类型。
将自定义的类类型转换成其他任何一种数据类型,采用转换函数。//声明在要转换的类体中的无数据类型(有返回值)、空参数的成员函数,
//不能定义到void的转换,也不能转换成数组或者函数类型。常定义为const形式
explicit关键字用于修饰构造函数。表示不允许在定义初始化对象时进行隐式转换
智能指针:
实质:类模板
头文件:memory
shared_ptr:共享资源智能指针,一种计数指针,当计数为0时,指针指向的对象会被删除
shared_ptr<类名>指针名(new 类名)//重载了*运算符 所以定义的指针名 不用写*
//重载了->,可以直接通过指针名->访问类成员
通过make_shared<Base>(Base());给shared_ptr开辟空间//在堆区开辟资源共享的空间,安全性高,执行结束后会自动析构
unique_ptr
同一时刻只能有一个unique_ptr指向给定对象(通过禁止拷贝语义、只有移动语义来实现)。
make_unique<>开辟空间
weak_ptr
弱指针(weak pointer),指向一个已经用shared_ptr进行管理的对象 只有当对象存在的时候,才需要对其进行访问
弱指针.expired()检测指向的空间是否存在
}
day9
{
容器:类模板
迭代器:操作容器
空间配置器:配置容器空间
仿函数:类通过重载括号运算符模拟函数的行为
vector:数组
vector<数据类型>变量名
变量名.size()计算元素个数
变量名.push_back尾部插入元素
访问元素:变量名[下标]或变量名.at(下标)
变量名.erase(),假擦除,实质是将元素的索引进行盖面
}
C++学习笔记
最新推荐文章于 2023-05-30 21:00:00 发布
本文详细介绍了C++的基本概念,包括函数、类、对象、继承、多态等核心特性。深入探讨了函数的默认参数、重载、内联函数以及模板的使用。同时,讲解了面向对象编程的四大原则:抽象、封装、继承和多态,并讨论了静态成员、友元、异常处理和智能指针等高级主题。此外,还涵盖了容器、迭代器和空间配置器的概念。
摘要由CSDN通过智能技术生成