C艹笔记--面向对象程序设计

news2025/2/23 23:21:42

文章目录

    • 类与对象简介
      • 类与结构的区别
      • 定义成员函数
    • 继承
      • 继承小总结
    • [C++中::和:, .和->的作用和区别](https://zhuanlan.zhihu.com/p/165992745)
      • 符号::和:的作用和区别
        • ::
        • :一般用来表示继承
        • 符号.和->的作用和区别
    • #include
      • #include""和#include<>区别
      • .h文件(声明)和.cpp文件(定义)
      • 头h文件中的保护措施(防止同一文件多次包含同一头文件)
    • h文件和cpp文件实战
      • h文件
        • #ifndef...#endif

在这里插入图片描述

类与对象简介

类需要实例化对象才能起作用。
样例:
在这里插入图片描述
关键字class表示类,一般首字符用大写字母表示,以示与对象名的区别。关键字public和protected(或private)表示访问控制。在类中说明的,要么是数据成员,要么是成员函数。它们或者说明为public的,或者说明为protected的,或者说明为private的。类具有封装性,它可以说明哪些成员是public的,哪些不是。说明了protected的成员,外部是不能访问的.

但是可以通过类的public成员函数间接地访问。

类与结构的区别

  • C++中,结构是用关键字struct声明的类,默认情况下其成员是公共(public)的。
  • C++中,默认情况下类(class)定义中的成员是private的。

定义成员函数

∷叫作用域区分符,指明一个函数属于哪个类或一个数据属于哪个类。∷可以不跟类名,表示全局数据或全局函数(即非成员函数)
类内定义成员函数
在这里插入图片描述

类外定义成员函数

类名加在成员函数名之前而不是加在函数的返回类型前

将类定义和其成员函数定义分开,是目前开发程序的通常做法。我们把类定义(头文件)看成类的外部接口,类的成员函数定义看成类的内部实现。将类拿来编制应用程序时,只需类的外部接口(头文件)。这和我们使用标准库函数的道理是一样的,即只需包含某函数声明的头文件。因为类定义中全部包含了类中成员函数的声明。
在这里插入图片描述

继承

C++的三种继承方式详解
C++继承详解
C++继承祥祥祥解
在实际运用中一般使用的都是public继承,几乎很少使用protected/private继承,也不提倡使用protected/private继承,因为protected/private继承下来的成员都只能在派生类的类里面使用,实际中扩展维护性不强。
在这里插入图片描述
在这里插入图片描述

1.基类private成员在派生类中无论以什么方式继承都是不可见的。(注意:这里的不可见是指基类的私有成员还是被继承到了派生类对象中,但是语法上限制派生类对象不管在类里面还是类外面都不能去访问它
2.如果基类成员不想在类外直接被访问,但需要在派生类中能访问,就定义为protected。
3.上述表格实质有个规律:基类的私有成员在派生类中都是不可见的,基类的其他成员在派生类中的访问方式为Min(成员在基类的访问限定符,继承方式)(这里的大小关系为public > protected > private)。

样例
在这里插入图片描述

继承小总结

  • 派生类继承基类的方式,决定基类中成员在派生类中的最高权限(高于则降权限)。
  • 派生类中的成员函数可以直接访问基类中的public和protected成员,但不能直接访问基类的private成员。
  • 通过派生类的对象访问从基类继承的成员,只能访问public成员。

若派生类想调用基类不可访问成员,只能通过调用基类可访问成员方法间接调用基类不可访问成员。

C++中::和:, .和->的作用和区别

符号::和:的作用和区别

::

  • ::是作用域运算符,A::B表示作用域A中的-名称B,A可以是名字空间、类、结构;
  • 类作用域操作符
  • “::”指明了成员函数所属的类。如:M::f(s)就表示f(s)是类M的成员函数。
    作用域,如果想在类的外部引用静态成员函数,或在类的外部定义成员函数都要用到。
    使用命名空间里的类型或函数也要用到(如:std::cout, std::cin, std::string 等等)
  • 表示“域操作符”
    例:声明了一个类A,类A里声明了一个成员函数void f(),但没有在类的声明里给出f的定义,那么在类外定义f时, 就要写成void A::f(),表示这个f()函数是类A的成员函数。
  • 表示引用成员函数及变量,作用域成员运算符
    例:System::Math::Sqrt() 相当于System.Math.Sqrt()

:一般用来表示继承

  1. 表示结构内位域的定义(即该变量占几个bit空间)
typedef struct _XXX{

unsigned char a:4;

unsigned char c;
};XXX
  1. 在构造函数后面,冒号起分割作用,是类给成员变量赋值的方法,初始化列表,更适用于成员变量的常量const型。
    构造函数,就是与类同名的函数,它与普通函数的区别在于,它没有返回类型。在构造函数后面紧跟着冒号加初始化列表,各初始化变量之间以逗号(,)隔开。
    例如:
class myClass
{
public :
    myClass();// 构造函数,无返回类型,可以有参数列表,这里省去
    ~myClass();// 析构函数
    int a;
    const int b;
}

myClass::myClass():a(1),b(1)// 初始化列表
{
}

关于“:”冒号的用法的说明:

  • 初始化列表的作用相当于在构造函数内进行相应成员变量的赋值,但两者是有差别的。

在初始化列表中是对变量进行初始化,而在构造函数内是进行赋值操作。两都的差别在对于像const类型数据的操作上表现得尤为明显:const 类型的变量必须在定义时进行初始化,而不能对const型的变量进行赋值,因此const类型的成员变量只能(而且必须)在初始化列表中进行初始化,如:

myClass::myClass()
{
    a = 1;// 没错,效果相当于在初始化列表中进行初始化
    b = 1;// 出错,const变量不能进行赋值操作;
}
2) 初始化的顺序与成员变量声名的顺序相同。
先看一下下面的程序:
myClass::myClass():b(1),a(b)
{
}

这样的执行结果a,b各是多少呢?b=1,a=1?不是,b=1而a是个随机数。这一点是相当重要,一般在初始化列表中进行初始化时,初始化的顺序应与声明的顺序保持一致,防止出现不必要的错误。

  • public:和private:后面的冒号,表示后面定义的所有成员都是公有或私有的,直到下一个"public:”或"private:”出现为止。"private:"为默认处理。
  • 类名冒号后面的是用来定义类的继承。
class 派生类名 : 继承方式 基类名
{

派生类的成员

};

这里的冒号起到的就是声名基类的作用,在基类类名前面可以加public/private/protected等标签,用于标识继承的类型,也可以省略, 省略的话,用class定义的类默认为private,用struct定义的类默认为public
与初始化列表一样的,这里也可以声名多个基类,各基类之间用逗号(,)隔开。

  • 条件语句(? : )

与?构成条件语句,作用相当于if else,如下;

int a,b,c;
a=3;
b=2;
c=a>b?a:b;// 如果a>b成立,则反a赋给c,否则把b赋给c

条件语句的结构为:
条件表达式?表达式1:表达式2
当条件表达式为true时,表达式的值为表达式1的值,否则为表达式2的值。

注意:
1)?:可以嵌套,但不推荐使用(难懂),例如:

int max = i>j ? i>k ? i : k : j>k ? j : k;

2)?:具有很低的优先级,例如:

int i = 3;
int j = 2;
cout << i>j?i:j;// 出错,<<比>具有更高的优先级,执行顺序为 ((cout<<i)>j)?i:j,相当于是比较cout<<i与j的大小,然后根据比较结果决定表达式值为i或j,这 显然要出错的,cout<<i的值是cout,不能跟整型数j进行比较。
cout << (i>j)?i:j;//输出1或0,相当于(cout<<(i>j))作为判决条件,来决定表达式的值为i或j,而 cout<<(i>j),i>j则输出1否则0,然后再将(cout<<(i>j))作为?:的条件,如果 cout正确执行则为1(true),否则为0(false),以此决定表达式值为i或j
cout <<(i>j?i:j);//i>j则输出i,否则输出j,表达式值为true如果cout正确执行,否则为false
  • 语句标签

通常跟goto配合使用,如:

step1: a = f1();
....
goto step1;

这种作法也不是很推荐,原因在于它破坏了语句的顺序执行;

  • switch语句中case后。

符号.和->的作用和区别

A.B则A为对象或者结构体; 点号(.):左边必须为实体。
A->B则A为指针,->是成员提取,A->B是提取A中的成员B,A只能是指向类、结构、联合的指针; 箭头(->):左边必须为指针;

->的优先级比较高==(*指针).
class A
{
public:
    int a = 0;
};
int main()
{
    A b;
    A *p = &b;
    b.a; //类类型的对象访问类的成员
    p->a; //类类型的指针访问类的成员
}

#include

C++头文件和cpp文件的原理
#include 是一个来自C语言的宏命令,它在编译器进行编译之前,即在预编译的时候就会起作用。#include的作用是把它后面所写的那个文件的内容,完完整整地、一字不改地包含到当前的文件中来。值得一提的是,它本身是没有其它任何作用与副功能的,它的作用就是把每一个它出现的地方,替换成它后面所写的那个文件的内容。简单的文本替换,别无其他
#include 一个文件(无论.h或是.cpp),仅仅是将文件中的代码复制一份到你的代码之中,头文件(.h)仅在编译过程中的预处理中起到作用。

#include""和#include<>区别

二者区别如下(开始搜索的位置不同):
  1、“”是表示从当前目录开始搜索,然后是系统目录和PATH环境变量所列出的目录。
  2、<>表示从系统目录下开始搜索,然后再搜索PATH环境变量所列出的目录,不搜索当前目录。
  正常情况下,自行定义的头文件应该用"",因为这些文件放在工程目录(也就是编译器的当前目录)下,而不是放在公共头文件目录下。
而系统提供的头文件,比如库函数的头文件,可以用<>。
这样效率最快。

.h文件(声明)和.cpp文件(定义)

关于C++ .h文件和.cpp文件的知识梳理
通常,在一个C++程序中,只包含两类文件——.cpp文件和.h文件。

  • .cpp文件被称作C++源文件,里面放的都是C++的源代码
  • .h文件则被称作C++头文件,里面放的也是C++的源代码,头文件不用被编译

注意这里提到了两个概念,一个是“声明”,一个是“定义”。简单地说:

  • “声明”则只是声明这个符号的存在,即告诉编译器,这个符号是在其他文件中定义的,我这里先用着,你链接的时候再到别的地方去找找看它到底是什么吧。声明的时候就只需要写出这个符号的原型了。
  • “定义”就是把一个符号完完整整地描述出来:它是变量还是函数,返回什么类型,需要什么参数等等。定义的时候要按C++语法完整地定义一个符号(变量或者函数)

需要注意的是,一个符号,在整个程序中可以被声明多次,但却要且仅要被定义一次

仅在.h 文件中进行变量和函数的声明而不进行定义(存在一些特例,比如class 的内敛成员函数,模板函数), 因为函数与变量的声明可以进行任意多次,而定义只能有一次。

头文件不用被编译。我们把所有的函数声明全部放进一个头文件中,当某一个.cpp源文件需要它们时,它们就可以通过一个宏命令#include包含进这个.cpp文件中,从而把头文件的内容合并到.cpp文件中去。当.cpp文件被编译时,这些被包含进去的.h文件的作用便发挥了。

函数声明和定义的分离十分简单,我们只需要在.h文件中写出函数返回值类型函数名、接受的参数,再到.cpp文件中去写函数的具体实现就行了。而变量的声明和定义的分离就要靠关键字extern 了。extern 主要有两个作用,其中一个是对指定单元强制使用C 的编译器进行编译,另一个便是声明变量的作用范围的关键字,其声明的函数和变量可以在本编译单元或其他编译单元中使用。
总结:当你需要定义一个变量给所有include 该头文件的单元共同使用时,你应该在.h文件中使用extern 关键字,表示该变量将在include这个头文件的编译单元中使用(即进行“声明”)。同时另外新建一个.cpp文件对该头文件中声明的变量进行统一定义(定义变量的文件实际上可以是任意include该头文件的.cpp文件,但为了避免混乱,我们通常约定是在和头文件同名的.cpp文件中进行定义,可以认为是一种规范)。

头h文件中的保护措施(防止同一文件多次包含同一头文件)

考虑一下,如果头文件中只包含声明语句的话,它被同一个.cpp文件包含再多次都没问题——因为声明语句的出现是不受限制的。然而,上面讨论到的头文件中的三个例外也是头文件很常用的一个用处。

那么,一旦一个头文件中出现了上面三个例外中的任何一个,它再被一个.cpp包含多次的话,问题就大了。因为这三个 例外中的语法元素虽然“可以定义在多个源文件中”,但是“在一个源文件中只能出现一次”。

设想一下,如果a.h中含有类A的定义,b.h中含有类B的定义,由于类B的定义依赖了类A,所以b.h中也#include了a.h。现在有一个源文件,它同时用到了类A和类B,于是程序员在这个源文件中既把a.h包含进来了,也把b.h包含进来了。

这时,问题就来了:类A的定义在这个源文件中出现了两次!于是整个程序就不能通过编译了。你也许会认为这是程序员的失误——他应该知道b.h包含了a.h——但事实上他不应该知道。

使用#define配合条件编译可以很好地解决这个问题。在一个头文件中,通过#define定义一个名字,并且通过条件编译#ifndef...#endif使得编译器可以根据这个名字是否被定义,再决定要不要继续编译该头文中后续的内容。这个方法虽然简单,但是写头文件时一定记得写进去。

h文件和cpp文件实战

.h文件中写出函数返回值类型、函数名、接受的参数,再到.cpp文件中去写函数的具体实现就行了
.cpp文件实现.h文件的声明

cpp文件实际上可以是任意include该头h文件的.cpp文件,但为了避免混乱,我们通常约定是在和头文件同名的.cpp文件中进行定义,可以认为是一种规范。

h文件

h:类声明,方法声明,const,define变量声明
注意:#ifndef...#endif

#ifndef…#endif

#ifndef…#endif属于预处理功能中三种(宏定义define ,文件包含include和条件编译)中的第三种—-条件编译

c++中的# ifndef 与#endif

#ifndef X标识符 //先测试x是否被宏定义过,如果被定义则返回假,如果没有被定义则返回真。
#define X标识符  
 	// 如果X没有被宏定义过,定义为X,并执行该语句
#endif   //终止if

在理论上来说可以是自由命名的,但每个头文件的这个“标识”都应该是唯一的。标识的命名规则一般是头文件名全大写,前面加下划线,并把文件名中的“.”也变成下划线,如:stdio.h

#ifndef _STDIO_H

#define _STDIO_H

......

#endif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2805.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

STM32入门——基本 GPIO 的输出控制

文章目录1 什么是 GPIO &#xff1f;1.1 GPIO 简介1.2 GPIO 硬件解析1.2.1 保护二极管1.2.2 P-MOS、N-MOS 管1.2.3 数据输入输出寄存器1.2.4 复用功能输出1.2.5 模拟输入输出1.3 GPIO 的工作模式1.3.1 输入模式 (模拟/浮空/上拉/下拉)1.3.2 输出模式 (推挽/开漏)1.3.3 复用功能…

基于Nodejs+vue开发实现酒店管理系统

作者简介&#xff1a;Java、前端、Pythone开发多年&#xff0c;做过高程&#xff0c;项目经理&#xff0c;架构师 主要内容&#xff1a;Java项目开发、毕业设计开发、面试技术整理、最新技术分享 项目编号&#xff1a;BS-QD-KS-002 一&#xff0c;项目简介 本项目使用纯前端技…

mysql约束

文章目录mysql约束非空约束唯一性约束主键约束使用自增列&#xff1a;AUTO_INCREMENTFOREIGN KEY约束CHECK约束mysql约束 为什么需要约束&#xff1f;为了保证数据的完整性什么叫约束&#xff1f;对表中字段的限制约束的分类&#xff1a; 角度1&#xff1a;约束的字段个数&…

吴峰光杀进 Linux 内核

【编者按】吴峰光&#xff0c;Linux 内核守护者&#xff0c;学生时代被同学戏称为“老神仙”&#xff0c;两耳不闻窗外事&#xff0c;一心只搞 Linux。吴峰光的 Linux 内核之路&#xff0c;是天赋、兴趣、耐心、坚持的综合&#xff0c;这从一个补丁前后迭代了 16 个版本后还进行…

【初识Netty使用Netty实现简单的客户端与服务端的通信操作Netty框架中一些重要的类以及方法的解析】

一.Netty是什么&#xff1f; Netty 由 Trustin Lee(韩国&#xff0c;Line 公司)2004 年开发 本质&#xff1a;网络应用程序框架 实现&#xff1a;异步、事件驱动 特性&#xff1a;高性能、可维护、快速开发 用途&#xff1a;开发服务器和客户端 Netty的性能很高&#xff0…

字符串匹配算法(BF、KMP)

目录 1、暴力匹配&#xff08;BF&#xff09;算法 2、KMP算法 1、暴力匹配&#xff08;BF&#xff09;算法 BF算法&#xff0c;即暴力(Brute Force)算法&#xff0c;是普通的模式匹配算法&#xff0c;BF算法的思想就是将目标串S的第一个字符与模式串T 的第一个字符进行匹配&a…

【树莓派不吃灰】配置samba,文件夹目录配置在闲置U盘,实现局域网文件共享

目录1. 前言2. 安装 Samba2.1 安装samba 和 samba-common-bin2.2 配置/etc/samba/smb.conf文件2.3 配置登录账号和密码2.4 重启 samba 服务2.5 回到windows&#xff0c;就可以在网络当中发现共享的文件夹3. 在Windows上挂载smb的共享目录3.1 打开windows的smb功能3.2 添加网络映…

Java --- springMVC实现RESTFul案例

一、使用springMVC实现RESTFul小案例 1.1、项目目录图&#xff1a; 1.2、代码实现&#xff1a; pom.xml文件&#xff1a; <packaging>war</packaging><!--添加依赖--><dependencies><!--SpringMVC--><dependency><groupId>org.spr…

黑马C++ 03 提高4 —— STL常用容器_string容器/vector容器/deque容器

文章目录一、string容器1. string基本概念2. string构造函数3. string赋值操作4. string字符串拼接5. string查找和替换6. string字符串比较7. string字符存取8. string字符串的插入和删除9. string子串二、vector容器(尾插尾删)1. vector基本概念2. vector构造函数3. vector赋…

【目标检测】基于yolov3的血细胞检测(无bug教程+附代码+数据集)

多的不说,少的不唠,先看检测效果图: 共检测三类:红细胞RBC、白细胞WBC、血小板Platelets Hello,大家好,我是augustqi。今天给大家带来的保姆级教程是:基于yolov3的血细胞检测(无bug教程+附代码+数据集) 1.项目背景 在上一期的教程中,我们基于yolov3训练了一个红细…

韩顺平linux(1-11小节)

运维工程师 服务器的规划、调试优化、日常监控、故障处理 物联网linux Linux主要指的是内核 ubuntu&#xff08;python偏爱&#xff09;&#xff0c;centos 发行版本 内核进行包装 1.4服务器领域 linux在服务器领域的应用是最强的。 linux免费、稳定、高效等特点在这里得到了很…

2019 Sichuan Province Programming Contest J. Jump on Axis

题目链接&#xff1a;https://codeforces.com/gym/102821/problem/J 题意&#xff1a;给你一个坐标k&#xff0c;每次从0开始走 每次有三个选择&#xff1a;选择1走一步&#xff0c;选择2走两步&#xff0c;选择3走三步 每次选第i个选择的时候&#xff0c;如果他没有被选过&…

MySQL是如何保证数据不丢失的

一.什么是两阶段提交 1.SQL语句&#xff08;update user set name‘李四’ where id3&#xff09;的执行流程是怎样的呢&#xff1f; 1.执行器先找引擎取 ID3这一行。ID 是主键&#xff0c;引擎直接用树搜索找到这一行。 2.如果 ID3 这一行所在的数据页本来就在内存中&#x…

力扣算法入门刷题

1、回文数 判断输入的整数是否是回文 我的一般思路&#xff1a; 将输入的整数转成字符串&#xff0c;再将这个字符串转成字符数组c&#xff0c;对字符数组进行遍历&#xff0c;如果第i个元素与第 c.length - i - 1 元素不相等&#xff0c;也就是通过比较首尾元素是否相同来判断…

自动化早已不是那个自动化了,谈一谈自动化测试现状和自我感受……

前言 从2017年6月开始接触自动化至今&#xff0c;已经有好几年了&#xff0c;从17年接触UI自动化&#xff08;unittestselenium&#xff09;到18年接触接口自动化&#xff08;unittestrequests&#xff09;再到18年自己编写自动化平台&#xff08;后台使用python的flask&#…

风、光、柴油机、蓄电池、电网交互微电网经济调度优化问题研究附Matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

爆破校园网的宽带

前提&#xff1a;学校的手机号前7位相同&#xff0c;宽带密码都是手机号后六位。仅供学习。 准备工作&#xff1a;电脑一台&#xff0c;把校园网的宽带水晶头插在电脑上&#xff0c; 步骤&#xff1a; winR输入Rasphone点击新建&#xff0c;宽带&#xff0c;输入宽带名称&am…

Vue复刻华为官网 (一)

1 分析 根据华为网页的布局&#xff0c;我们大体上可以将其划分为7个盒子&#xff0c;如下&#xff0c;由于写一个这样的网页再加上部分动态效果&#xff0c;需要的时间很长&#xff0c;本篇博客只记录了div1、div2、div3的静态效果轮播图的实现。 2 顶部盒子的实现 想要实现的…

【C++AVL树】4种旋转详讲

目录 引子&#xff1a;AVL树是因为什么出现的&#xff1f; 1.AVl树的的特性 2.AVl树的框架 3.AVL树的插入 3.1四种旋转&#xff08;左单旋、右单旋、左右双旋、右左双旋&#xff09; 3.1.1左单旋 3.1.2右单旋 3.1.3左右双旋 3.1.4右左双旋 总结 引子&#xff1a;AVL树是因…

【单片机】单片机的核心思想

&#x1f4ac;推荐一款模拟面试、刷题神器 、从基础到大厂面试题&#xff1a;&#x1f449;点击跳转刷题网站进行注册学习 目录 一、单片机的核心思想 二、单片机核心图 三、上拉电路及应用 排阻的优势 四、单片机的输入输出模式 1、接收外部电压信号 2、向外输出电压信…