高程-类和对象

news2025/6/8 7:30:04

面向对象编程(OOP)

特征:抽象、多态、封装、继承

既然有结构体struct了,那么使用类class的好处是什么呢?C中struct的成员可以任意访问,对于一些隐私信息是不允许的。为了保护类中的数据安全,在C++中将类中的成员分为两类:公有成员(用public声明);私有成员(用private声明)

私有成员(包括数据成员和成员函数)只能被类内的成员函数访问,不能被类外的对象访问。

公有成员(包括数据成员和成员函数)既可以被类内的成员函数访问,又可以被类外的对象访问。

实现类的外部接口

如果不添加pubic,类内的所有成员默认私有,而C的结构体默认公有。一般来说,把需要保护的数据设为私有,成员函数设为公有。成员函数为进入类的入口。

类的定义一般形式

class 类名{
    数据成员类型 数据成员列表
};

每个类可以没有成员,也可以有多个成员

类成员可以是数据或函数

所有成员必须在类的内部声明,一旦类定义完成后,没有其他方式添加成员。

每个类还可以包含成员函数,能够访问类自身的所有成员

类的数据成员

class Cube{
    long color;//数据成员
    double x,y,z,side;//数据成员
    int a[10];
    char *s;
    char &r;
    void *p;
}

内联成员函数

类的成员函数可以指定为inline,即内联函数。
默认情况下,在类体中定义的成员函数若不包括循环等控制结构符合内联函数要求时,C++会自动将它们作为内联函数处理(隐式inline)。


class Data { //Data类定义
    int getx(){ return x;} //内联成员函数
    inline int gety(){return y;} //显式指定内联成员函数
    inline void setxy(int_x,int_y)://显式指定内联成员函数
    void display();
    int x,y;
};
inline void Data::setxy(intx,int_y)//内联成员函数
{
    x=_x,y=_y;
}
void Data::display()//非内联成员函数
{
    ... //函数体
}

在类的外部定义成员函数 

class 类名{
    返回类型 函数名(类型1 参数名1,类型2 参数名2,...);
    //成员函数声明
    返回类型 函数名(类型1,类型2,...);
};
返回类型 类名::函数名(形式参数列表)
{
    函数体//访问类的数据成员
}

说明:(::)是作用域限定符

成员函数重载及默认参数

成员函数的存储方式

通常,C++会为每个对象的数据成员分配各自独立的存储空间,像结构体成员那样。

类的声明

class Point;//Point类声明,非Point类定义

 在创建类的对象之前,必须完整地定义该类。这样,编译器就会给类的对象准备相应的存储空间。
同样地,在使用引用或指针访问类的成员之前,必须已经定义类。
类不能具有自身类型的数据成员。然而,只要类名一经出现就可以认为该类己声明。因此,类的数据成员可以是指向自身类型的指针或引用。

class Point;//Point类声明,非Point类定义,因为没有类体
class Line {
    Point a;//错误,不能使用仅有类声明而没有类定义的类定义数据对象
    Point *pp,&rp;//正确,只有类声明,即可用它定义该类的指针或引用
    Line b;//错误,类不能具有自身类型的数据成员
    Line*pl,&rl;//正确,类可以有指向自身类型的指针或引用的数据成员
};

对象 

对象是类的实例

对象的定义 

1、先定义类类型再定义对象

类名 对象名列表;

2、定义类类型的同时定义对象 

class 类名{ //类体

        成员列表

}对象名列表;

一般而言,定义类型时不分配存储空间,定义对象时将为其分配存储空间 

对象的动态建立和释放

利用new运算符可以动态地分配对象空间,delete运算符释放对象空间。

用new运算动态分配得到的对象是无名的,它返回对象的内存单元的起始地址。程序通过这个地址可以间接访问这个对象,因此需要定义一个指向类的对象的指针变量来存放该地址。
在执行new运算时,如果内存不足,无法开辟所需的内存空间C++编译器会返回一个0值指针。因此,只要检测返回值是否为0.就可以判断动态分配对象是否成功,只有指针有效时才能使用对象指针。

当不再需要使用由new建立的动态对象时,必须用delete运算予以撤销。例如:

delete p;//撤销p所指向的Point对象

释放了p所指向的对象。此后程序不能再使用该对象,
注意,new建立的动态对象不会自动被撤销,即使程序运行结束也是如此,必须人为使用delete撤销

访问对象中的成员可以有3种方法


1、通过对象名和对象成员引用运算符(.)访问对象中的成员;

对象名.成员

对象名.成员函数(实参列表)

从类外部只能访问公有成员

2、通过指向对象的指针和指针成员引用运算符(->)访问对象中的成员;

对象指针->成员

对象指针->成员函数(实参列表)

3、通过对象的引用变量和对象成员引用运算符(.)访问对象中的成员;

对象引用变量名.成员

对象引用变量名.成员函数(实参列表)

对象赋值(同类)

对象名1=对象名2;

构造函数

创建对象时自动被调用(ctor)

在创建对象时初始化对象,为对象数据成员赋初始值

类的数据成员不能在类定义时初始化(原因:类定义时并没有产生一个实体,而是建立一种数据模型,不占用内存空间)

如果一个类中所有数据成员都是共有的,则可以在定义对象时对数据成员初始化

构造函数的定义

C++规定构造函数的名字与类的名字相同,并且不能指定返回类型。定义形式为:

类名(形式参数列表)

{

函数体

}

构造函数可以没有形参,有如下两种形式:

类名()

{

函数体

}

类名(void)

{
函数体

}

关于构造函数的说明:
(1)构造函数是在创建对象时自动执行的,而且只执行一次,并先于其他成员函数执行。构造函数不需要人为调用,也不能被人为调用。
(2)构造函数一般声明为公有的(public),因为创建对象通常是在类的外部进行的。如果构造函数声明为保护的(protected)或私有的(protected),那就意味着在类外部创建对象(并调用构造函数)是错误的。换言之,这样的类是不能由外部实例化,只能由类内部实例化,这种情况不是通常的做法。

(3)在构造函数的函数体中不仅可以对数据成员初始化,而且可以包含任意其他功能的语句,例如分配动态内存等,但是一般不提倡在构造函数中加入与初始化无关的内容
(4)每个构造函数应该为每个数据成员提供初始化。否则将使那些数据成员处于未定义的状态。而使用一个未定义的成员是错误的
(5)带参数的构造函数中的形参,是在定义对象时由对应的实参给定的,用这种方法可以方便地实现对不同对象进行不同的初始化,需要注意,实参必须与构造函数的形参的个数、次序、类型一致。

构造函数的重载

在一个类中可以定义多个构造函数版本,即构造函数允许被重载只要每个构造函数的形参列表是唯一的。一个类的构造函数数量是没有限制的。一般地,不同的构造函数允许建立对象时用不同的方式来初始化数据成员。

尽管在一个类中可以包含多个构造函数,但是对于每一个对象来说建立对象时只执行其中一个,并非每个构造函数都被执行。

带默认参数的构造函数

1、必须在类内指定默认参数

2、如果构造函数的全部参数都指定了默认值,则在定义对象时可以给一个或几个实参,也可以不给出实参。这时,就与无参数的构造函数有歧义了。

3、在一个类中定义了带默认参数的构造函数后,不能再定义与之有冲突的重载构造函数。

拷贝构造函数

拷贝构造函数,又称复制构造函数,是一种特殊的构造函数,它由编译器调用来完成一些基于同一类的其他对象的构建及初始化。其形参必须是引用,但并不限制为const,一般普遍的会加上const限制。 

对于普通类型的对象来说,它们之间的复制是很简单的,例如:

int a = 100;
int b = a; 

而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量。
下面看一个类对象拷贝的简单例子。

类名(const 类名 &参数)

#include<iostream>
using namespace std;
class CExample
{
private:
    int a;
public:
    //构造函数
    CExample(int b)
    {
        a=b;
        printf("constructor is called\n");
    }
    //拷贝构造函数
    CExample(const CExample & c)
    {
        a=c.a;
        printf("copy constructor is called\n");
    }
    //析构函数
    ~CExample()
    {
        cout<<"destructor is called\n";
    }
    void Show()
    {
        cout<<a<<endl;
    }
};
int main()
{
    CExample A(100);
    CExample B=A;
    B.Show(); 
    return 0;
}


程序运行结果如下:

constructor is called
copy constructor is called
100
destructor is called
destructor is called          

使用条件

析构函数 

析构函数:

当对象脱离其作用域时(例如对象所在的函数已调用完毕),系统会自动执行析构函数。(dtor)析构函数往往用来做“清理善后的工作(例如在建立对象时用new开辟了一段内存空间,则在该对象消亡前应在析构函数中用delete释放这段存储空间)

C++规定析构函数的名字是类名的前面加一个波浪号(~)。其定义形式为:

~类名()

{
        函数体

}

析构函数不返回任何值,没有返回类型,也没有函数参数。由于没有函数参数,因此它不能被重载。换言之,一个类可以有多个构造函数,但是只能有一个析构函数,

何时调用析构函数:


(1)对象在程序运行超出其作用域时自动撤销,撤销时自动调用该对象的析构函数。如函数中的非静态局部对象
(2)如果用new运算动态地建立了一个对象,那么用delete运算释放该对象时,调用该对象的析构函数。

需要特别注意对它们的调用时间和在使用构造函数和析构函数时,调用次序。
构造函数和析构函数的调用很像一个栈的先进后出,调用析构函数的次序正好与调用构造函数的次序相反。最先被调用的构造函数其对应的(同一对象中的)析构函数最后被调用,而最后被调用的构造函数,其对应的析构函数最先被调用。
可简述为:先构造的后析构,后构造的先析构。

调用次序

对象数组和对象指针

对象数组

将具有相同类类型的对象有序地集合在一起便构成了对象数组,以一维对象数组为例,其定义形式为:

类名 对象数组名[常量表达式];


一维对象数组有时也称为对象向量,它的每个元素都是相同类类型的对象。

例如表示平面上若干个点,可以这样定义:
Point points[100];//表示100个点

关于对象数组的说明:
(1)在建立对象数组时,需要调用构造函数。如果对象数组有100个元素,就需要调用100次构造函数。
(2)如果对象数组所属类有带参数的构造函数时,可用初始化列表按顺序调用构造函数,使用复制初始化来初始化每个数组元素。(3)如果对象数组所属类有单个参数的构造函数时,定义数组时可以直接在初值列表中提供实参。
Point P[3]={Point(1,2),Point(5,6),Point(7,8)};//三个实参Student S[5]={20,21,19,20,19};//Student类只有一个数据成员

(4)对象数组创建时若没有初始化,则其所属类要么有合成默认构造函数(此时无其他的构造函数),要么定义无参数的构造函数或全部参数为默认参数的构造函数(此时编译器不再合成默认构造函数)
(5)对象数组的初始化式究竟是什么形式,,本质上取决于所属类的构造函数。因此,需要明晰初始化实参与构造函数形参的对应关系,避免出现歧义性。
(6)如果对象数组所属类含有析构函数,那末每当建立对象数组时,按每个元素的排列顺序调用构造函数;每当撤销数组时,按相反的顺序调用析构函数。

对象指针

在建立对象时,编译器会为每一个对象分配一定的存储空间,以存放其成员。对象内存单元的起始地址就是对象的指针。可以定义一个指针变量,用来存放对象的指针。指向类对象的指针变量的定义形式为:

类名 *对象指针变量名 =初值

文章内容来源

C++程序设计_中国大学MOOC(慕课) (icourse163.org)

一文看懂C++类的拷贝构造函数所有用法(超详细!!!)-CSDN博客

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

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

相关文章

Ubuntu系统使用Docker本地部署Android模拟器并实现公网访问

文章目录 1. 虚拟化环境检查2. Android 模拟器部署3. Ubuntu安装Cpolar4. 配置公网地址5. 远程访问小结 6. 固定Cpolar公网地址7. 固定地址访问 本文主要介绍如何在Ubuntu系统使用Docker部署docker-android安卓模拟器&#xff0c;并结合cpolar内网穿透工具实现公网远程访问本地…

为什么要纯C语言手搓GPT-2,Karpathy回应网友质疑

ChatGPT狂飙160天&#xff0c;世界已经不是之前的样子。 新建了免费的人工智能中文站https://ai.weoknow.com 新建了收费的人工智能中文站https://ai.hzytsoft.cn/ 更多资源欢迎关注 几天前&#xff0c;前特斯拉 Autopilot 负责人、OpenAI 科学家 Andrej Karpathy 发布了一个仅…

RAGFlow:基于OCR和文档解析的下一代 RAG 引擎

一、引言 在人工智能的浪潮中&#xff0c;检索增强生成&#xff08;Retrieval-Augmented Generation&#xff0c;简称RAG&#xff09;技术以其独特的优势成为了研究和应用的热点。RAG技术通过结合大型语言模型&#xff08;LLMs&#xff09;的强大生成能力和高效的信息检索系统…

消息队列之-----------------zookeeper机制

目录 一、ZooKeeper是什么 二、ZooKeeper的工作机制 三、ZooKeeper特点 四、ZooKeeper数据结构 五、ZooKeeper应用场景 5.1统一命名服务 5.2统一配置管理 5.3统一集群管理 5.4服务器动态上下线 5.5软负载均衡 六、ZooKeeper的选举机制 6.1第一次启动选举机制 6.2非…

怎么区分开关电源的PFM与PWM模式?

原文来自微信公众号&#xff1a;工程师看海&#xff0c;与我联系&#xff1a;chunhou0820 看海原创视频教程&#xff1a;《运放秘籍》 大家好&#xff0c;我是工程师看海。 DCDC开关电源有两种常见的工作模式&#xff0c;就是我们常听说的PWM模式和PFM模式&#xff0c;一种是普…

算法训练营第二十三天(二叉树完结)

算法训练营第二十三天&#xff08;二叉树完结&#xff09; 669. 修剪二叉搜索树 力扣题目链接(opens new window) 题目 给定一个二叉搜索树&#xff0c;同时给定最小边界L 和最大边界 R。通过修剪二叉搜索树&#xff0c;使得所有节点的值在[L, R]中 (R>L) 。你可能需要改…

2024年第十七届 认证杯 网络挑战赛 (A题)| 保暖纤维的保暖能力 |数学建模完整代码+建模过程全解全析

当大家面临着复杂的数学建模问题时&#xff0c;你是否曾经感到茫然无措&#xff1f;作为2022年美国大学生数学建模比赛的O奖得主&#xff0c;我为大家提供了一套优秀的解题思路&#xff0c;让你轻松应对各种难题。 让我们来看看认证杯 网络挑战赛 (A题&#xff09;&#xff01…

两数相加(leetcode)

给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。 请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外&#xff0c;这两个数都不会以 0 …

基于Java的图书借阅网站, java+springboot+vue开发的图书借阅管理系统 - 毕业设计 - 课程设计

基于Java的图书借阅网站&#xff0c; javaspringbootvue开发的图书借阅管理系统 - 毕业设计 - 课程设计 文章目录 基于Java的图书借阅网站&#xff0c; javaspringbootvue开发的图书借阅管理系统 - 毕业设计 - 课程设计一、功能介绍二、代码结构三、部署运行1、后端运行步骤2、…

社会工程学——setoolkit的简单使用(克隆钓鱼网站)

Social Engineer Toolkit&#xff08;SET&#xff09;是一个开源的社会工程学攻击工具包&#xff0c;旨在模拟和执行多种社会工程学攻击&#xff0c;例如钓鱼、恶意软件传播和其他形式的社会工程学攻击。SET由David Kennedy&#xff08;也被称为"ReL1K"&#xff09;开…

ubuntu20.04下搜狗输入法的安装

1、安装 fcitx 输入法的框架 sudo apt install fcitx-bin sudo apt-get install fcitx-table 2、Ubuntu下的默认浏览器火狐搜索 搜狗输入法 搜狗输入法linux-首页 &#xff08;下载x86_64) 3、安装依赖 sudo apt install libqt5qml5 libqt5quick5 libqt5quickwidgets5 qml-modu…

取数游戏(dfs)

前言&#xff1a; 该题取自洛谷P1123&#xff0c;题主用的dfs&#xff08;深度优先搜索&#xff09; 题目描述&#xff1a; 数据范围&#xff1a; 思路&#xff1a; 思路见代码&#xff0c;注释的很清晰嗷 AC代码&#xff1a; #include <iostream> #include <alg…

【学习笔记】R语言入门与数据分析1

数据分析 数据分析的过程&#xff1a; 数据采集 数据存储 数据分析 数据挖掘 数据可视化 进行决策 数据挖掘 数据量大 复杂度高&#xff0c;容忍一定的误差限 追求相关性而非因果性 数据可视化 直观明了 R语言介绍 R是免费的&#xff08;开源软件、扩展性好&#xff09;…

PlanUML和Mermaid哪个好?

引言 在当今信息化快速发展的时代&#xff0c;数据可视化和图表工具不仅对于程序员&#xff0c;也对于非技术背景的人士至关重要。绘图工具可以帮助我们更好地理解和表达复杂的概念或数据流。PlantUML和Mermaid是两款被广泛使用的绘图语言&#xff0c;它们都能够通过简洁的文本…

4.11学习总结

一.IO流 一.java中IO的初步了解 (一).概念: Java中I/O操作主要是指使用Java进行输入&#xff0c;输出操作. Java所有的I/O机制都是基于数据流进行输入输出&#xff0c;这些数据流表示了字符或者字节数据的流动序列。Java的I/O流提供了读写数据的标准方法。任何Java中表示数据…

基于Python豆瓣电影数据可视化分析系统的设计与实现

大数据可视化项目——基于Python豆瓣电影数据可视化分析系统的设计与实现 2024年4月最新编写的新项目 项目介绍 本项目旨在通过对豆瓣电影数据进行综合分析与可视化展示&#xff0c;构建一个基于Python的大数据可视化系统。通过数据爬取收集、清洗、分析豆瓣电影数据&#xff…

【SpringBoot】SpringBoot项目快速搭建

本文将介绍Springboot项目的快速搭建 快速创建SpringBoot项目 打开IDEA在File->New->Project中新建项目 点击左侧的Spring Initializr 输入以下信息&#xff1a; Name 项目名称Group 根据公司域名来&#xff0c;或者默认com.example【倒序域名】Package Name 包名&am…

【java探索之旅】走进循环结构 深入解析while、for和do while的用法

&#x1f3a5; 屿小夏 &#xff1a; 个人主页 &#x1f525;个人专栏 &#xff1a; Java编程秘籍 &#x1f304; 莫道桑榆晚&#xff0c;为霞尚满天&#xff01; 文章目录 &#x1f4d1;前言一、循环结构1.1 while循环1.2 while代码示例1.3 break1.4 continue 二、for循环2.1 基…

蓝桥杯第十一届c++大学B组详解

目录 1.字符串排序 2.门牌制作 3.即约分数 4.蛇型填数 5.跑步锻炼 6.七段码 7.成绩统计 8.回文日期 9.字串分值和 10.平面切分 1.字符串排序 题目解析&#xff1a;这个题目真没搞懂。有会的大佬教我一下谢谢。 2.门牌制作 题目解析&#xff1a;出过超级多这类题目&am…

Java springboot+vue宠物爱心组织管理系统附赠万字文档

项目演示视频: &#xff08;有文档&#xff09;Java springboot宠物爱心组织管理系统 项目介绍: &#xff08;有文档&#xff09;Java springboot宠物爱心组织管理系统 技术&#xff1a; 基于springboot Vue 的宠物爱心组织管理系统&#xff08;宠物爱心组织管理系统&#xf…