首页 > 编程语言 >c++基础思维导图2

c++基础思维导图2

时间:2022-08-31 19:12:07浏览次数:62  
标签:思维 函数 导图 成员 c++ int 对象 重载 继承

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++,int,对象,重载,继承
From: https://www.cnblogs.com/jerry-autumn/p/16644243.html

相关文章

  • 【C++】引用与指针的区别
    安全性首先引用要比指针要安全,因为引用不能更改绑定,但是指针可以更改指向,此外指针可以有多级,但是引用一般只有一级。在使用指针的时候,我们往往需要使用断言,判断指针是不是......
  • VectorCAST在汽车电子C++代码测试的应用
    随着汽车行业的发展,软件定义汽车已成为汽车产业达成的共识发展趋势,软件在汽车产品中也承担着越来越重要的角色,车身域各功能的实现,少则几千行代码,动辄百万行代码。随着汽车......
  • 新发现的几个不错的c++库
    1.coost包含了各种常用的库,比boost轻量级的基于c++11的库https://github.com/idealvin/coost2.ImGui一个较少依赖的gui界面库https://github.com/ocornut/imgui ......
  • 【C++】ceil floor round 函数
    https://blog.csdn.net/dangzhangjing97/article/details/81279862?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRL......
  • CCF 201503-1 图像旋转(C++)
    好像旋转矩阵有更好的做法,但是我觉得这样也足够了,如果需要更好的做法,大家得自己在去找一下。我主要是找了下规律,然后做出来的#include<iostream>#include<bits/stdc+......
  • C++学习笔记-day03
    1、嵌套循环2、跳转语句continue不会使整个循环终止,break会跳出循环//输出2,跳过了1gotoA;cout<<1<<endl;A:cout<<2<<endl;3、数组......
  • C++ 简单设计模式之简单工厂
    一、简单工厂一个工厂类能够根据传入参数而决定创建出哪一种产品类的实例二、类设计//手机classPhone{public: virtualvoidmodel()=0;};//华为手机clas......
  • 侯捷老师c++11重点
    作者:还有offer嘛链接:https://www.nowcoder.com/discuss/962212?page=3来源:牛客网  •指针、引用、数组、内存•右值引用与完美转发•引用与指针区别•C和......
  • 产品化思维之-工作流本质和几个概念
    这篇文章是约10年前我和同事的一个关于工作流的讨论的一个备忘,现在转到这里做了备份。现在看有些观念和认识落伍了,也不一定正确,但是仍有一定的参考价值。---------------......
  • 南京地区寻志同道合的前端后端C++小伙伴(成功推荐奖励500元)
    我们是南京小微企业,目前虽处于疫情大环境下,但是我们公司由于强悍的技术背景以及所属行业特殊,处于项目多人少尴尬情况,作为公司合伙人,我们每天都很着急,经过长达半年的招聘,......