c++基础思维导图2

结构体

结构体的基本概念:用户自定义的数据类型

结构体定义和使用

  • struct 结构体名{结构体成员}
  • struct 结构体名 变量名;

struct 结构体名 变量名 = {成员1,成员2}

定义式struct 可以不加上分号,但是创建一个结构体数组的时候需要加上分号

定义结构体的关键字是struct,不可以省略;

关键字struct 可以省略;

结构体变量利用操作符" . "访问成员

结构体数组

  • struct 结构体名 数组名{元素个数}={{},{}.{}...{}}

结构体和指针

  • 操作符->可以通过访问结构体属性
  • Student s1;

Student *p=&s1;

结构体嵌套结构体

结构体做函数的参数

  • 如果修改主元素的数据就地址传入,不修改就按值传入;
  • 函数中的参数改为指针为减少内存空间而不会复制新的版本出来

小作业:通讯录管理系统

程序中的内存模型

针对c++面向对象技术的详细讲解

c++程序在执行的时候大方向分为四个区域

  • 1、代码区

    • 存放函数体二进制代码,由操作系统进行管理的
    • 代码区是共享的
    • 代码区是只读的
  • 2、全局区

    • 存放全局变量和静态变量以及常量
    • 全局区还包括常量区,字符串常量和其他常量
    • 该区域里面的数据结束后由操作系统释放
  • 3.栈区

    • 由编译器自动分配释放。存放函数的参数值,局部变量,局部常量等
    • 栈区的数据在函数执行之后会自动的释放,所以不要返回局部变量的地址
  • 4.堆区

    • 由程序员分配和释放,若程序员不释放,程序结束时操作系统回收

    • new

      • 例子:

#include

#include

#include

using namespace std;

int *fun_c(){

int * p =new int(10);

return p;

}

int main(){

int * p = fun_c();

cout <<* p<<endl;

//打印的结果是10;

return 0;

}

- new返回的是数据类型的指针

- delete

    - 释放内存

    - 释放数组的时候使用delete[]

不同区域存放的数据赋予了不同的生命周期,给我们更大的灵活编程

c++中的引用

引用的作用就是给变量起别名

语法:数据类型 &别名=原名

例子

  • #include

#include

using namespace std;

int main(){

int a = 10;

int &b =a;

b = 20;

cout << "a =

"<<a<<endl;

cout << "b =

"<<b<<endl;

return 0; //结果是a=b=20;

}

  • #include

#include

using namespace std;

int main(){

int a = 10;

int &b =a;

int c = 30;

b = c;

cout << "a =

"<<a<<endl;

cout << "b =

"<<b<<endl;

cout << "c =

"<<b<<endl;

return 0; //结果是a=b=c=30;

}

注意

  • 引用必须要初始化
  • 引用初始化后不可以改变

引用做函数参数

  • 作用:函数传参时,可以利用引用的技术让形参修饰实参
  • 优点:可以简化指针修改实参

函数传递

  • 地址传递
  • 值传递
  • 引用传递

引用做函数的返回值

  • 不能返回局部变量的引用,可以使用静态变量的引用

引用的本质就是一个指针常量,引用一旦初始化后就不可以发生改变

常量的引用

  • const int & ref = 10;

    • 加上const之后编译器将代码修改:

int temp = 10;

const int & ref = temp;

- 加上const 变为只读状态不可以修改
  • int & ref =10是不合法的

  • 例子

    • #include

using namespace std;

void show(int&);

int main(){

int a =10;

show(a);

cout << a <<endl;//改变了a 的值,输出的结果是1000;

return 0;

}

void show(int &b){

b =1000;

}

  • 作用就是传递函数的形参的时候使用const int &就不会改变原来传入的变量的值

函数高级

函数的默认参数

  • 如果调用函数的时候传入了参数的值就优先使用传入的值,没有传入就使用默认参数

  • 如果某个位置已经有了默认参数,那么这个位置往后,从左到右都必须要有默认值

    • 错误示范:

#include

using namespace std;

int fun(int,int,int);

int main(){

int t =fun(10,20,30);

cout << t <<endl;

return 0;

}

int fun(int a=10,int b,int c){//这里的a已经有了默认值那么所有的形参都应该设置默认值,否则就会报错

return a+b+c;

}

  • 声明有了函数的默认值实现就不能有(声明和实现只能有一个默认参数),为了避免二义性

函数占位参数

  • 就是写函数形参的时候只是写数据的类型

  • 占位参数还可以有默认参数

    • 例子:

int fun(int a,int b,int= 20);

int main(){

int t =fun(5,10);

cout << t <<endl;

return 0;

}

int fun(int a,int b,int c){

return a+b+c;

}

函数的重载

  • 函数名可以相同,提高复用性

  • 需要满足的条件

    • 同一个作用域下;
    • 函数名称相同;
    • 函数参数类型不同或者个数不同或者顺序不同;
  • 注意:函数的返回值不可以作为函数重载的条件;

  • 引用作为重载条件,默认参数产生重载的歧义

函数重载的注意事项

类和对象

c++面向对象三大特性:封装、继承、多态

具有属性的事物叫做对象,具有相同性质的对象可以抽象成类

对象特性

  • 构造函数和析构函数

    • 构造函数

      • 构造函数是对象的初始化

      • 构造函数主要作用是创建对象时为对象的成员属性赋值,构造函数由编译器自动调用,无需手动调用

      • 语法

        • 类名(){}
        • 构造函数没有返回值也不写void
        • 函数名称和类相同
        • 构造函数可以有参数,因此可以发生重载
        • 程序在调用对象时候自动调用构造,不需要手动调用
    • 析构函数

      • 析构函数是清理

      • 析构函数主要作用时对象销毁前系统自动调用,执行一些清理工作

      • 语法

        • ~类名(){}
        • 析构函数没有返回值也不写void
        • 函数名称与类名相同,在名称前加上符号~
        • 析构函数不可以由参数,因此不可以发生重载
        • 程序在对象摧毁前会自动析构,无需手动调用只会调用一次
      • 作用:析构函数可以将堆区开辟数据做释放操作

构造函数的分类及调用

- 按照参数分类:有参构造和无参构造;

    - 按照类型分类:普通构造和拷贝构造

       - 拷贝调用函数使用的时机

           - 使用一个已经创建完毕的对象来初始化一个新对象

           - 值传递的方式给函数参数传递

           -

以值的方式返回局部对象

- 三种调用方式:括号法、显示法、隐式转换法

    - 注意:1.匿名对象

特点:当前执行结束后,系统会理机回收掉匿名函数;

2.不要利用拷贝构造函数,初始化匿名对象

3.隐式转换法

- 构造函数和析构函数是编译器自动调用,完成对象初始化和清理工作

-

如果不提供析构和构造函数,编译器会提供,提供的都是空实现

  • 初始化列表

    • example

Person():m_A(10),m_B(20),m_C(30){}

- Person(int a,int b,int

c):m_A(a),m_B(b),m_C(c){}

  • 深拷贝和浅拷贝

    • 浅拷贝:简单的赋值拷贝操作;

      • 浅拷贝带来的问题就是堆区的内存重复释放
    • 深拷贝:在堆区重新申请空间,进行拷贝操作

      • 如果属性有在堆区开辟的,一定要自己提供拷贝函数,防止浅拷贝带来的问题
  • 类对象作为类成员

    • 当其他类的对象作为本类成员,构造时候先构造类对象
  • 静态成员

    • 静态成员就是成员表变量和函数前面加上关键字static,称为静态成员

    • 静态成员变量

      • 所有对象共享一份数据
      • 在编译阶段分配内存
      • 类内声明,类外初始化
    • 静态成员函数

      • 所有对象共享同一函数
      • 静态成员函数只能访问静态成员变量
  • 成员变量和成员函数分开存储

    • 在c++中,类内的成员变量和成员函数分开存储,只有非静态成员变量才属于类的对象上
    • 空对象占内存空间是1;

c++编译器会给每个空对象也分配一个字节空间,是为了区分空对象占内存的位置

- 空对象占字节数是1,为了表示对象的内存位置;对象中有静态成员变量,所占字节数还是1,说明了静态成员变量不属于类对象上,同理成员函数不属于类对象上
  • this指针

    • this指针指向被调用的成员函数所属的对象
    • this指针式隐含每一个非静态成员函数的一种指针
    • this指针的用途:

1.当形参和成语那变量同名时,可以用this指针来区分;

2.在类的非静态成员函数中返回对象本身可使用return *this

  • 空指针访问成员函数

    • c++中空指针也是可以调用成员函数的,但是也要注意没有用到的this指针;如果用到this指针,需要加以判断保证代码的健壮性
  • const修饰成员函数

    • 常函数

      • 成员函数后加const后我们称为这个函数为常函数
      • 常函数内不可以修改成员属性
      • 成员属性声明时关键mutable,在常函数中依然可以修改
    • 常对象

      • 声明对象前加const称该对象为常对象
      • 常对象只能调用常函数

友元

  • 友元的关键字为friend

  • 友元的目的就是为了一个函数或者类访问另一个类中私有成员

  • 友元的三种实现

    • 全局函数做友元
    • 类做友元
    • 成员函数做友元

运算符重载

  • 运算符重载概念:对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型
  • 对于内置的数据类型的表达式的运算符是不可能改变的;

不要滥用重载;

  • (加减乘除)运算符重载

    • 例子

      • #include

using namespace std;

class Person{

public:

int m_a;

int m_b;

/* Person operator+(Person
&p){

Person temp;

    temp.m_a =

this->m_a+p.m_a;

temp.m_b =

this->m_b+p.m_b;

return temp; //使用成员函数运算符重载

}*/

};

//使用全局函数运算符重载

Person operator+(Person &p1,Person &p2){

Person temp;

    temp.m_a = p1.m_a+p2.m_a;

    temp.m_b = p1.m_b+p2.m_b;

    return temp;

}

void test01(){

Person p1;

p1.m_a = 10;

p1.m_b = 10;

Person p2;

p2.m_a = 20;

p2.m_b = 20;

Person p3 = p1+p2;

cout

<<p3.m_a<<endl;

cout <<

p3.m_b<<endl;

}

int main(){

test01();

return 0;

}

  • 左移运算符重载

    • 作用:可以输出自定义数据类型
  • 递增运算符重载

    • 作用:通过重载递增运算符,实现自己的整形数据
    • 注意:前自增运算符重载时返回的时引用,后自增运算符重载时返回的时值,自减同理
  • 赋值运算符重载

  • 关系运算符重载

  • 函数调用运算符重载

继承

继承的作用

  • 作用:定义类时,下级别的成员除了拥有上一级的共性,还有自己的特性,这时候可以考虑继承的技术,减少重复代码
  • 派生类时从基类中继承过来的,一类是自己增加的成员,从基类继承过来的表现其共性,而新增的成员体现了其个性

继承语法

  • class 子类:继承方式 父类

class A:public B;

A类为子类或派生类

B类为父类或基类

继承的方式有三种

  • 公共继承;
  • 保护继承;
  • 私有继承;

继承中同名处理方式

  • 继承中同名的静态成员在子类对象上如何进行访问

    • 访问子类同名成员--直接访问即可
    • 访问父类同名成员,需要加作用域
  • 继承中同名静态成员函数如何进行访问

    • 和同名静态成员相同
  • 继承的访问方式

    • 通过对象进行访问
    • 通过类名进行访问
  • 子类中如果出现和父类相同的成员就会把父类中的成员全部隐藏,解决方法就是加上作用域

  • 多继承语法

    • 语法:class 子类:
      继承方式 父类1, 继承方式 父类2 ...
    • 多类继承可能会引发父类中有同名成员出现,需要加作用域区分
    • 在实际开发中不建议多用多继承
  • 菱形继承概念

    • 两个派生类继承同一个基类

    • 又有某个类同时继承连个派生类

    • 这种继承被称为菱形继承或者钻石继承

    • 菱形继承容易出现多继承二义性的情况,也容易浪费内存

    • 利用虚继承,解决菱形继承问题,继承之前,加上关键字 virtual 变为虚继承,其中最开始的基类称为虚基类

      • 其内部本质上是一个指针,用一个虚指针指向同一个数据
      • 语法 class
        类名: virtual public 要继承类名;

封装

意义:

1.将属性和行为作为一个整体,表现生活中的事物;

2.将属性和行为加以权限控制

权限控制

  • 三种访问权限:

  • 公共权限(public):成员类内可以访问,类外可以访问

  • 保护权限(protected):成员类内可以访问,类外不能访问

    • 子类可以访问父类保护的内容
  • 私有权限(private):成员类内可以访问,类外不能访问

    • 子类不可以访问父类私有的内容

c++中struct和class的区别

  • 唯一的区别是默认的访问权限不同
  • struct默认访问权限是公有
  • class默认访问权限是私有

成员属性设置为私有的优点

  • 将所有成员属性设置为私有,可以自己控制读写权限

  • 对于写权限,我们可以检测数据的有效性

  • 例子

    • #include

#include

using namespace std;

class student{

public:

void set_name(string name){

    m_name = name;

}

string get_name(){

    return m_name;

}

int get_age(){

    return age;

}

void set_classes(string

class1){

classes=class1;

}

private:

    string m_name;//可读可写

    int age=18;//可读

    string classes;//可写不可读

};

int main(){

student st1;

st1.set_name("jerry");

st1.set_classes("english

education");

cout <<"学生的名字是:

"<<st1.get_name()<<endl;

cout <<"学生的年龄是:

"<<st1.get_age()<<endl;

return 0;

}

多态

多态分为两类

  • 静态多态

    • 函数重载和运算符重载属于静态多态,复用函数名
  • 动态多态

    • 派生类和虚函数实现运行时多态

静态多态和动态多态的区别

  • 静态多态的函数地址早绑定-编译阶段就确定函数地址
  • 动态多态的函数地址晚绑定-运行阶段确定函数地址

多态优点

  • 代码组织结构清晰
  • 可读性强
  • 利于前期和后期的扩展以及维护
  • 组织结构清晰

在实际的开发中是开闭原则,对扩展进行开发,对修改进行关闭;

c++的开发中提倡利用多态设计组织架构,因为多态的优点有很多

纯虚函数和多态类

  • 在多态中,通常父类中虚函数的实现是毫无意义的,主要都是调用子类重写内容,因此可以将虚函数改为纯虚函数

  • 纯虚函数的语法:virtual 返回类型 函数名 (参数列表) = 0;

  • 当类中出现了纯虚函数,这个类也称为抽象类

  • 抽象类的特点

    • 无法实例化对象
    • 子类必须重写抽象类中的纯虚函数,否则也属于抽象类

虚析构和纯虚析构

  • 多态使用时,如果子类中属性开辟堆区,那么父类指针在释放时无法调用到子类的析构代码。

解决方法:将父类中的析构函数改为虚析构或者纯虚析构

  • 虚析构和纯虚析构共性:

1.可以解决父类指针释放子类对象;

2.都需要具有具体的函数实现;

虚构和纯虚析构区别:

1.如果纯虚析构,该类属于抽象类,无法实现实例对象

  • 虚构语法:virtual ~类名(){}

  • 纯虚构语法:virtual ~类名() =
    0;

  • 总结

    • 1.虚析构或者纯虚析构就是用来解决通过父类指针释放子类对象;
    • 2.如果子类中没有堆区数据,可以不写为虚析构或者纯虚析构;
    • 3.拥有纯虚析构函数的类也属于抽象类;

c++基础思维导图2的更多相关文章

  1. java 基础-思维导图

    思维导图的好处 最近看了一些文章的思维导图,发现思维导图真是个强大的工具.了解了思维导图的作用之后,觉得把它运用到java上应该是个不错的想法,这样回顾知识点的时候一目了然,快速知道自己的短板. 思维 ...

  2. java基础思维导图,让java不再难懂

    java基础思维导图,让java不再难懂 原文链接  https://my.oschina.net/u/3080373/blog/873056 最近看了一些文章的思维导图,发现思维导图真是个强大的工具 ...

  3. python开发基础--思维导图

    开始学习python,相当于零基础 非自学,自学的痛苦不想体会和尝试,毕竟不会很友好,知乎上看到很多说自学的好处啊噼里啪啦的.嗯,说的很对,但是我偏不听,略略略.锻炼我的自学能力,这还需要锻炼吗,百度 ...

  4. javascript基础 思维导图2

    来源于:http://www.cnblogs.com/xianyulaodi/p/5886128.html 1.javascript数据类型 2.javascript数组 3.javascript运算 ...

  5. java基础思维导图

    如果图片看不清楚的可以把图片另存为桌面放大看哈

  6. Hadoop基础思维导图

  7. Unity3d 脚本基础 思维导图

    盘点下Unity的脚本知识.

  8. java语法基础思维导图

  9. c#基础思维导图

随机推荐

  1. Centos 创建新的虚拟环境

    1. conda env list 查看目前已经存在的虚拟环境,注意新取的虚拟环境的名字不能和目前已存在的虚拟环境的名字相同! 2. conda create -n [环境名] [指定python版本 ...

  2. 自嗨ReentrantReadWriteLock

    import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util ...

  3. CSRF跨站请求伪造与XSS跨域脚本攻击讨论

    今天和朋友讨论网站安全问题,聊到了csrf和xss,刚开始对两者不是神明白,经过查阅与讨论,整理了如下资料,与大家分享. CSRF(Cross-site request forgery):跨站请求伪造 ...

  4. 这就是艺术「GitHub 热点速览 v.22.25」

    作者:HelloGitHub-小鱼干 不知道写了那么久代码的你,是否还记得"代码写诗"这个词,它是用来形容代码的优雅.但是本周的项目,虽然你看到的是代码的成品,也会惊讶于它的艺术感 ...

  5. C++ 练气期之一文看懂字符串

    C++ 练气期之细聊字符串 1. 概念 程序不仅仅用于数字计算,现代企业级项目中更多流转着充满了烟火气的人间话语.这些话语,在计算机语言称为字符串. 从字面上理解字符串,类似于用一根竹签串起了很多字符 ...

  6. Zabbix 5.0:通过LLD方式自动化监控阿里云RDS

    Blog:博客园 个人 之前做了RDS监控,由于 RDS 实例梳理增多,手动添加的方式已经不够效率,故改为LLD(Low-level discovery)方式做监控. 什么是LLD LLD(Low-l ...

  7. 全国土壤阳离子交换量CEC空间分布数据

    数据下载链接:百度云下载链接​ 土壤阳离子交换量,简称CEC,是指土壤胶体所能吸附各种阳离子的总量.土壤阳离子交换量 cation exchange capacity 即CEC 是指土壤胶体所能吸附各 ...

  8. go 编程规范

    如果没有编程规范会有什么问题? 哪些地方可以需要指定规范? 非编码类规范:编码规范 非编码规范 开源规范 http://www.ruanyifeng.com/blog/2011/05/how_to_c ...

  9. 【小程序自动化Minium】三、元素定位- WXSS 选择器的使用

    最近更新略疲,主要是业余时间多了几个变化.比如忙活自己的模拟赛车驾舱升级.还跟朋友筹备一个小程序项目.另外早上的时间留给背单词了... 上一章中讲到Page接口的get_element()与get_e ...

  10. 软件测试—Day2

    day2 Q:面试过程中,性能测试你测试什么?关注的点是什么? A:程序的响应时间,系统的吞吐量,以及并发用户数,和tps,qps,以及DB的IOPS,和服务器的系统资源(CPU和内存).通过一定的工 ...