C++笔记:类和对象

news2024/10/7 4:26:35

类和对象

        认识类和对象

         先来回忆一下C语言中的类型和变量,类型就像是定义了数据的规则,而变量则是根据这些规则来实际存储数据的容器。类是我们自己定义的一种数据类型,而对象则是这种数据类型的一个具体实例。类就可以理解为类型,而对象就可以理解为变量,而且对象是更加高级的变量。

        类型 = 类型数据 + 类型操作

        比如double类型

        他的数据类型占用8字节,并且可以表示成小数。

        类型操作可以加减乘除,但是它不支持模(%)运算。

        那么类就是包含了类型数据和类型操作的一个集合。

        也可以理解为数据就是类的属性,操作就是类的行为

        通过下面我定义的一个人的类,那么height,sex, age都是这个类的类型数据,而类型操作就是函数run和函数speak。

class People {
    double height;//身高
    char sex;//性别
    int age;//年龄
    string name;//姓名
    void run() {//跑
        cout << "I can run" << endl;
    }
    void speak() {//说话
        cout << "I can speak" << endl;
    }
};

        那么我需要一个特定的人的时候,我就需要定义一个对象用来存这个特定人的属性。

        下面的用类定义一个对象,并且对他的属性进行赋值。

People a;
a.name = "Zhang san";
a.age = 18;
a.sex = '1';//女0,男1
a.height = 1.89;

        而我需要这个人进行说话或者跑时,就需要调用他相应的操作,也就是函数。

a.run();
a.speak();

        访问权限

        public:是公共的资源,是谁都可以访问的资源,比如空气,阳光,公共场合都是谁都可以访问进行使用的。

        private:是私有的资源,是只能类自己进行访问的资源,比如每个人自己的私人物品,是只能自己使用和访问的。

        protected:是受保护的资源,是只能自己访问以及自己的子类访问的资源,比如你儿子可以使用你的东西。(在后续文章继承时会用到protected权限)

        friendly:是在关键字friend声明后,它允许被声明后的类或函数访问这一个类的私有或受保护的资源,比如你的好兄弟在你的允许下可以访问和使用你的私人物品。(在后续的文章中会更新到使用)

        重点:这里的访问权限是规定的类外对该类类内的访问权限。

        比如我在一个类中定义了一个访问权限为私有的方法,那么我只能在这个类的内部进行调用,在类外是无法调用的,除非我对这个方向进行了friend友元声明。

        对于为什么要为什么要有访问权限的设置,看如下代码:

#include<iostream>
using namespace std;


class People {
public :
int age;
    void speak() {
        cout << "my age is "<< age << endl;
        return ;
    }
};


int main() {
    People a;
    a.age = -100;
    a.speak();
    return 0;
}

        如果对于age是public公有访问的,那么在设置年龄的将不会受到限制,对于这份代码可能没有问题,如果在以后设计项目或者工程时,就会造成灾难性的错误。

        那么正确的写法应该如下,把age设置为私有的,对age赋值时,定义一个函数来进行对age赋值,并判断值是否在正确范围内,对于获取age值也定义一个函数进行来获取。

#include<iostream>
using namespace std;


class People {
public :
    void speak() {
        cout << "my age is "<< age << endl;
        return ;
    }
    void set_age(int x) {
        if (age <= 0 || age > 1000) {
            perror("your age is error\n");
            exit(1);
        }
        age = x;
        return ;
    }
    int get_age() {
        return age;
    }
private :
    int age;
};


int main() {
    People a;
    a.set_age(-100);
    a.speak();
    return 0;
}

构造函数和析构函数

        定义一个对象的流程:

     对于构造函数的详细解析如下代码:

#include<iostream>
using namespace std;

class A {
public :
    A() {//默认构造函数
        cout << "default constructor" << endl;
    }
    //如果这里没有const关键字,传入的对象是const声明的那么就会报错
    //如果没有&(引用),那么将会造成无限套娃的拷贝构造
    //假如这里没有&,那么这里的形参就相当于实参给他赋值
    //而赋值就是 A a = b, b是实参传入的值
    //那这里就会又调用构造函数,形成无限套娃
    A(const A &a) {
        this->x = a.x;
        this->y = a.y;
        cout << "copy constructor" << endl;
    }
    A(int x, int y) {//有参构造函数
        cout << "have parameter constructor" << endl;
        this->x = x;//this表示当前对象的地址
        this->y = y;
    }
    void operator=(const A &a) {//这个函数是=运算符重载,是类中默认有的
        cout << "this is assigment"  << endl;
        return ;
    }
    A(int x) {//转换构造函数
        cout << "conversion constructor" << endl;
        this->x = x;
        this->y = 0;
    }
    void output() {
        cout << "(" << x << ", " << y << ")" << endl;
    }
    ~A() {//析构函数
        cout << "destructor" << endl;
    }
private :
    int x, y;
};


void func(A a) {
    cout << "func : ";
    a.output();
    return ;
}


int main() {
    A a;//调用默认构造函数
    cout << "1-------------------------" << endl;
    A b(1, 2);//调用有参构造
    cout << "2-------------------------" << endl;
    //这里就调用了拷贝构造函数
    A e = b;
    cout << "3-------------------------" << endl;
    //这里只是运用了普通赋值运算符
    //通过执行会发现没有执行任何构造函数
    a = b;
    cout << "4-------------------------" << endl;
    //调用转换构造,将int类型转换为A类型
    //这里也可以是另一个类型的对象,那也是转换构造
    //不过还需要从新定义一个需要转换构造的函数,里面的参数就是对应的类型
    A c(3);
    cout << "5-------------------------" << endl;
    //这里调用的是拷贝构造函数,将对象b进行拷贝给函数形参a
    func(b);
    func(c);
    cout << "6-------------------------" << endl;
    //对于这中函数调用情况
    //这里就会用到转换构造
    //他会隐式的将int类型5通过转换构造转会为A类型
    func(5);
    cout << "7-------------------------" << endl;
    //这里相当于A d(4);
    //这里可以这样理解
    //等号类型相同编程才能通过
    //那么4,int类型就会通过转换构造变成A类型
    //如果没有转换构造那么就编译无法通过
    A d = 4;
    a = 6;
    cout << "8-------------------------" << endl;
    return 0;
}

构造函数的初始化列表

构造函数中的初始列表使用:

#include<iostream>
using namespace std;

class C {
public:
    C(int n) {
        this->num = n;
        cout << "C coversion constructor" << endl;
    }
    void output() {
        cout << num;
    }
private :
    int num;
};

class A {
public :
    //:后面是构造函数的初始化列表
    A(int a) : a(a), b(10), c(6) {
        cout << "A constructor" << endl;
    }
    void output() {
        cout << " " <<a << " " << b << " ";
        c.output();
        cout << endl;
        return ;
    }
private :
    int a, b;
    C c;
};


int main() {
    A a(2);
    a.output();
    return 0;
}

构造函数和析构函数的调用顺序

如下这份代码:

#include <iostream>
#include <string>
using namespace std;


class A {
public :
    A() {};
    A(string n)  {
        name = n;
        cout << name << " class A construtor" << endl;
    }
    ~A() {
        cout << name << " class A destructor" << endl;
    }
int *p;
private :
    string name;
};

class B {
public :
    //:a(a)
    //:后面是构造函数时,最该对象中的成员属性进行初始化操作
    B(string n, A &a) : a(a){
        name = n;
        cout << name << " class B construtor" << endl;
        //new关键字可以理解为,C语言中malloc去堆区中开辟一段空间
        a.p = new int[10];
        return ;
    }
    A &a;//创建一个引用属性,这里&a可以暂时理解为取a的地址
    ~B() {
        //delete就相当于C语言中的free对开辟空间的释放
        delete a.p;
        cout << name << " class B destructor" << endl;
    }
private :
    string name;
};


int main() {
    A a("a");
    B b("b", a);
    return 0;
}

执行结果:

        可以发现,析构顺序是构造顺序反过来的,通过代码可以发现在B中的有参构造中用到了a对象的引用,然后对a对象的p指针开辟了一段空间,如果析构时顺序和构造顺序一样的那么,在析构b对象时,去delete a.p去释放开辟的空间时,a对象已经被析构掉了,那就也无法去找a对象中的指针p了。

        

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

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

相关文章

「翻版周慧敏」海底骚逆天长腿贺30岁生日

有「翻版周慧敏」之称的苏皓儿&#xff08;Chloe&#xff09;&#xff0c;日前原来已是她迎来30岁生日&#xff0c;她也在IG分享潜水靓相。火红色比坚尼尽骚她的苗条身材和长腿&#xff0c;就连网民也十分佩服&#xff0c;说&#xff1a;「三字头都咁靓好屈机&#xff01;」 Ch…

MySQL 核心模块揭秘 | 14 期 | 回滚整个事务

回滚整个事务要怎么清除 binlog 日志&#xff0c;InnoDB 又会进行哪些操作&#xff1f; 作者&#xff1a;操盛春&#xff0c;爱可生技术专家&#xff0c;公众号『一树一溪』作者&#xff0c;专注于研究 MySQL 和 OceanBase 源码。 爱可生开源社区出品&#xff0c;原创内容未经授…

电商价格监测合规性探讨

品牌在做控价、数据分析的过程中&#xff0c;都需要先有数据作为支撑&#xff0c;也就是说要先采集数据&#xff0c;价格监测也是如此&#xff0c;监测的基础是采集&#xff0c;现在主流的采集形式是爬虫采集&#xff0c;可以理解为人工采集的升级版&#xff0c;以机器代替人工…

Python基于深度学习的车辆特征分析系统

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

西晋从建立到灭亡51年历史

西晋的建立&#xff0c;也标志着三国时期的结束&#xff0c;也开启了中国历史上的一个新时代。下面让我们来揭开西晋从建立到灭亡51年的历史。 1、高平陵事变 曹丕去世后&#xff0c;魏明帝曹睿继位&#xff0c;但曹睿却英年早逝&#xff0c;幼子曹芳继位。 司马懿受曹睿托孤…

微服务之网关路由

一、概述 1.1认识网关 什么是网关&#xff1f; 顾明思议&#xff0c;网关就是网络的关口。数据在网络间传输&#xff0c;从一个网络传输到另一网络时就需要经过网关来做数据的路由和转发以及数据安全的校验。 更通俗的来讲&#xff0c;网关就像是以前园区传达室的大爷。 外…

vue 常用的日历排班,带农历显示组件(2024-04-16)

显示当前月日历组件&#xff0c;里面带农历或节日显示 后面可以丰富一些国家法定节假期的业务需求 代码 js-calendar.js 文件 var lunarInfo [0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, //1900-19090x04ae0, 0x0a5b6, 0…

了解 Unity AI:从初学者到高级的综合指南

游戏中的AI是什么? 游戏中的人工智能是指利用人工智能技术使视频游戏中的非玩家角色和实体智能地行动、做出决策、对游戏环境做出反应,并提供引人入胜的动态游戏体验。什么是NPC? NPC 代表“非玩家角色”。NPC 是视频游戏、角色扮演游戏中不受人类玩家控制的角色。它们是计算…

Python-VBA函数之旅-exec函数

目录 一、exec函数的常见应用场景&#xff1a; 二、exec函数安全使用注意事项&#xff1a; 三、exec函数与eval函数对比分析&#xff1a; 1、exec函数&#xff1a; 1-1、Python&#xff1a; 1-2、VBA&#xff1a; 2、相关文章&#xff1a; 个人主页&#xff1a;神奇夜光…

【word技巧】如何锁定word文档格式不变?

Word文档编辑完成之后不想被其他人修改格式&#xff0c;应该如何设置&#xff1f;限制编辑来搞定。 打开word文档设置限制编辑的界面&#xff0c;我们只勾选【限制对选定样式设置格式】&#xff0c;点击底下的设置&#xff0c;除了勾选第一个选项以外&#xff0c;还可以勾选上…

通过 Ollama、Langchain 实现 RAG

RAG 是什么 RAG 在 Langchain 上的定义是&#xff0c;作为大语言模型最常用的场景就是问答系统&#xff0c;可以针对特别来源数据做问题回答&#xff0c;就是私有数据&#xff0c;这就是 RAG&#xff0c;英文全称是Retrieval Augmented Generation。就是对现有模型数据的增广&…

树和二叉树(一)

一、树 非线性数据结构&#xff0c;在实际场景中&#xff0c;存在一对多&#xff0c;多对多的情况。 树( tree&#xff09;是n (n>0&#xff09;个节点的有限集。当n0时&#xff0c;称为空树。 在任意一个非空树中&#xff0c;有如下特点。 1.有且仅有一个特定的称为根的节点…

公园高速公路景区校园IP网络广播音柱SIP音柱

公园高速公路景区校园IP网络广播音柱SIP音柱 适用于学校、车站、教堂、工厂、仓库、公园停车场及露天市场高速公路等场所播放录制语音文件或背景音乐节目&#xff0c;专业一体化音箱设计&#xff0c;高强度防水设计&#xff0c;符合IP54防护等认证&#xff0c;数字化产品&…

一个开源的全自动视频生成软件MoneyPrinterTurbo

只需提供一个视频 主题 或 关键词 &#xff0c;就可以全自动生成视频文案、视频素材、视频字幕、视频背景音乐&#xff0c;然后合成一个高清的短视频。 一&#xff1a;功能特性 完整的 MVC架构&#xff0c;代码 结构清晰&#xff0c;易于维护&#xff0c;支持 API 和 Web界面…

用Scrapy抓取当当网站数据

setting.py实验目的及要求&#xff1a; 【实验目的】 通过本实验了解Scrapy爬虫框架&#xff1b;熟练掌握Scrapy的基本使用方法和常用技巧。 【实验要求】 使用Scrapy框架&#xff0c;抓取网站商品信息&#xff08;京东、淘宝、当当等任选一个&#xff09;&#xff0c;并将结…

软考 系统架构设计师系列知识点之大数据设计理论与实践(8)

接前一篇文章&#xff1a;软考 系统架构设计师系列知识点之大数据设计理论与实践&#xff08;7&#xff09; 所属章节&#xff1a; 第19章. 大数据架构设计理论与实践 第3节 Lambda架构 19.3.3 Lambda架构介绍 1. 批处理层 2. 加速层 对加速层批处理视图建立索引&#xff0c…

如何将Oracle 中的部分不兼容对象迁移到 OceanBase

本文总结分析了 Oracle 迁移至 OceanBase 时&#xff0c;在出现三种不兼容对象的情况时的处理策略以及迁移前的预检方式&#xff0c;通过提前发现并处理这些问题&#xff0c;可以有效规避迁移过程中的报错风险。 作者&#xff1a;余振兴&#xff0c;爱可生 DBA 团队成员&#x…

【网络编程】如何创建一个自己的并发服务器?

hello &#xff01;大家好呀&#xff01; 欢迎大家来到我的网络编程系列之如何创建一个自己的并发服务器&#xff0c;在这篇文章中&#xff0c;你将会学习到在Linux内核中如何创建一个自己的并发服务器&#xff0c;并且我会给出源码进行剖析&#xff0c;以及手绘UML图来帮助大家…

基于Docker构建CI/CD工具链(十)总结

我们用九篇文章简单的介绍了使用Docker构建CICD工具链&#xff0c;希望对你的工作有所帮助。 基于Docker构建CI/CD工具链&#xff08;一&#xff09;构建基础工具镜像 基于Docker构建CI/CD工具链&#xff08;二&#xff09;快速搭建Gitlab代码库 基于Docker构建CI/CD工具链&…

【DM8】ODBC

官网下载ODBC https://www.unixodbc.org/ 上传到linux系统中 /mnt下 [rootstudy ~]#cd /mnt [rootstudy mnt]# tar -zxvf unixODBC-2.3.12.tar.gz [rootstudy mnt]# cd unixODBC-2.3.12/ [rootstudy unixODBC-2.3.12]# ./configure 注意&#xff1a;若是报以上错 则是gcc未安…