C++笔记:类和对象

类和对象

        认识类和对象

         先来回忆一下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进行拷贝给函数形参afunc(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.hqwc.cn/news/625270.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【数据结构与算法】用两个栈实现一个队列

题目 用两个栈&#xff0c;实现一个队列功能 add delete length 队列 用数组可以实现队列&#xff0c;数组和队列的区别是&#xff1a;队列是逻辑结构是一个抽象模型&#xff0c;简单地可以用数组、链表实现&#xff0c;所以数组和链表是一个物理结构&#xff0c;队列是一个逻…

Servlet-Filter实现反爬虫

以前用DotNetCore实现过反爬虫功能。在tomcat里面可以利用Servlet的Filter类实现请求的控制来达到反爬虫功能&#xff0c;进而增强JRT的web安全。 实现黑名单过滤器&#xff0c;对在黑名单列表的IP的所有请求都跳转到警告页面&#xff0c;业务各种请求自行定义加入黑名单 /* …

爆肝3k字!掌握Spring与Redis的高效交互:从Jedis到Spring Data Redis

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

数字孪生技术的应用场景

数字孪生技术是一种新兴技术&#xff0c;具有广阔的应用前景。目前&#xff0c;数字孪生技术已经在以下几个领域得到了广泛应用。数字孪生技术是一种具有革命性的技术&#xff0c;它将深刻改变我们的生活和工作方式。随着数字孪生技术的不断发展&#xff0c;我们可以期待在未来…

Javascript中的this关键字指向,2024年最新阿里前端开发面试解答

先自我介绍一下&#xff0c;小编浙江大学毕业&#xff0c;去过华为、字节跳动等大厂&#xff0c;目前阿里P7 深知大多数程序员&#xff0c;想要提升技能&#xff0c;往往是自己摸索成长&#xff0c;但自己不成体系的自学效果低效又漫长&#xff0c;而且极易碰到天花板技术停滞…

【C++】适配器· 优先级队列 仿函数 反向迭代器

目录 适配器&#xff1a;适配器的应用&#xff1a;1. 优先级队列&#xff1a;仿函数&#xff1a;更深入的了解仿函数&#xff1a;一个关于不容易被注意的知识点&#xff1a; 2. 反向迭代器&#xff1a;&#xff08;list为例&#xff09; 适配器&#xff1a; 我们先来谈来一下容…

设计模式——2_9 模版方法(Template Method)

人们往往把任性也叫做自由&#xff0c;但是任性只是非理性的自由&#xff0c;人性的选择和自决都不是出于意志的理性&#xff0c;而是出于偶然的动机以及这种动机对感性外在世界的依赖 ——黑格尔 文章目录 定义图纸一个例子&#xff1a;从文件中获取信息分几步&#xff1f;Rea…

Adobe AE(After Effects)2017下载地址及安装教程

Adobe After Effects是一款专业级别的视觉效果和动态图形处理软件&#xff0c;由Adobe Systems开发。它被广泛用于电影、电视节目、广告和其他多媒体项目的制作。 After Effects提供了强大的合成和特效功能&#xff0c;可以让用户创建出令人惊艳的动态图形和视觉效果。用户可以…

MapReduce 机理

1.hadoop 平台进程 Namenode进程: 管理者文件系统的Namespace。它维护着文件系统树(filesystem tree)以及文件树中所有的文件和文件夹的元数据(metadata)。管理这些信息的文件有两个&#xff0c;分别是Namespace 镜像文件(Namespace image)和操作日志文件(edit log)&#xff…

vscode编译c++报错解决方案

1&#xff0c;xxxx cl.exe 一大串什么非程序员的(应该是这些&#xff09;,就是看一些谁的&#xff0c;调用了Visual Studio的编译软件去运行。建议&#xff0c;不要这样搞。 解决方案1&#xff1a;每次用就看这个文章&#xff08;个人觉得很麻烦&#xff09;&#xff1a;仅当…

java正则表达式教程

什么是正则表达式&#xff1a; 正则表达式是一种用来描述字符串模式的语法。在 Java 中&#xff0c;正则表达式通常是一个字符串&#xff0c;它由普通字符&#xff08;例如字母、数字、标点符号等&#xff09;和特殊字符&#xff08;称为元字符&#xff09;组成。这些特殊字符可…

NLP基础—jieba分词

jieba分词 支持四种分词模式 精确模式 试图将句子最精确地切开,适合文本分析;全模式 把句子中所有的可以成词的词语都扫描出来, 速度非常快,但是不能解决歧义;搜索引擎模式 在精确模式的基础上,对长词再次切分,提高召回率,适合用于搜索引擎分词。paddle模式 利用Paddle…