首页 > 其他分享 >类和对象的基本概念

类和对象的基本概念

时间:2023-05-13 22:46:06浏览次数:22  
标签:函数 对象 构造 拷贝 属性 基本概念 构造函数

封装:

属性和行为作为一个整体,来表现各种事物。

将属性和行为加以权限控制(private,public,protected)

一些术语:

属性(成员属性,成员变量),行为(成员函数,成员方法);统称为成员。

实例化(通过一个类,创建一个对象的过程)

访问权限:

当一个形参是函数对象时,该函数体内部不可以访问该对象的私有属性。

当一个类的成员是另外一个类的对象时(或则说该成员的类型是另外一个类),则该类不能访问它的成员的私有属性(也就是另外一个类的私有属性),除非两者是友元的关系。

控制私有成员的读写权限:

(1)读和写:

(2)只读:

(3)加一个判断:

(4)只写:

构造和析构函数 :

只会调用一次

构造函数在对象创建处会被调用,析构函数在对象所在作用域结束后会被调用

有参构造:

就是构造函数的括号中含有参数,有参构造也可以在函数体内对参数进行一些操作。最重要的目的是给成员属性赋初值。

拷贝构造:

只有真正的在拷贝构造的函数体中显式赋值拷贝的对象的成员才会拷贝给被拷贝对象

但是当自己不写拷贝构造函数时,系统会自动将拷贝的对象的成员属性传递给被拷贝对象的成员属性。

 1     //Point(const Person& p)
 2     //{
 3     //    m_Age = p.m_Age;
 4     //    cout << "Person的拷贝构造函数调用" << endl;
 5     //}
 6 
 7 
 8 void test01()
 9 {
10     Point p;
11     p.m_Age = 18;
12     Point p2(p);
13     cout << "p2的年龄为:" << p2.m_Age << endl;
14 }
15 int main()
16 {
17     test01();
18 }

 

创建对象的方法:

括号法创建对象:

显示法:

匿名对象:

打印结果说明函数没有执行完毕,匿名函数就被释放掉了

隐式转换法:

拷贝构造何时会被调用:

函数以值传递的方式进行参数传递的时候,如果形参是对象的话,就调用了拷贝构造,当实参给形参初始化的时候相当于隐式转换法

构造函数调用规则:

构造函数按参数分类可以分为有参构造和无参构造,按类型分类可以分为普通构造和拷贝构造。

默认情况下,C++编译至少给一个类添加3个函数
默认构造函数(无参,函数体为空)
默认析构函数(无参,函数体为空)
默认拷贝构造函数,对属性进行值传递

构造函数调用规则如下:

如果用户定义有参构造函数,C++不在提供默认无参构造,但是会提供拷贝构造
如果用户定义拷贝构造函故,C++不会再提供其他构造函数

(编译器不会提供意味着必须要自己写,不写就用不了。编译器提供意味着自己不写也可以用)

析构函数的作用:

 1 class Person
 2 {
 3 public:
 4     Person()
 5     {
 6         cout << "Person的默认构造函数调用" << endl;
 7     }
 8     Person(int age,int height)
 9     {
10         cout << "Person的有参构造函数调用" << endl;
11         m_Age = age;
12         m_Height = new int(height);
13     }
14     ~Person()
15     {
16         //析构代码,将堆区开辟数据做释放操作
17         if (m_Height != NULL)
18         {
19             delete m_Height;
20             m_Height = NULL;
21             cout << "Person的析构函数调用" << endl;
22         }
23     }
24     int m_Age;
25     int* m_Height;
26 };

浅拷贝和深拷贝:

 

如果利用编译器提供的拷贝构造函数,就会做浅拷贝操作。

 

浅拷贝出现问题在于:对象中成员属性具有指针类型,并且该指针指向一块堆区的内存,这样在做拷贝构造时,当调用两个析构函数的时候就会造成堆区的内存重复释放。

也就是说P2会把P1所有内容原封不动的拷贝过来,当P2析构时释放掉m_Height所指向的堆区内存时后P1再来释放这块内存就会非法操作。

 

 

 1 class Person
 2 {
 3 public:
 4     Person()
 5     {
 6         cout << "Person的默认构造函数调用" << endl;
 7     }
 8     Person(int age,int height)
 9     {
10         cout << "Person的有参构造函数调用" << endl;
11         m_Age = age;
12         m_Height = new int(height);
13     }
14     //Person(const Person& p)
15     //{
16     //    m_Age = p.m_Age;
17     //    cout << "Person的拷贝构造函数调用" << endl;
18     //}
19     ~Person()
20     {
21         //析构代码,将堆区开辟数据做释放操作
22         if (m_Height != NULL)
23         {
24             delete m_Height;
25             m_Height = NULL;
26             cout << "Person的析构函数调用" << endl;
27         }
28     }
29     int m_Age;
30     int* m_Height;
31 };
32 void test01()
33 {
34     Person p(18,168);
35     Person p2(p);
36     cout << "p的年龄为:" << p.m_Age << "身高为:" << *p.m_Height << endl;
37     cout << "p2的年龄为:" << p2.m_Age << "身高为:" << *p2.m_Height << endl;
38 }
39 int main()
40 {
41     test01();
42 }

 解决方法是进行深拷贝,重新申请一块堆区内存,让P2中的指针指向这块堆区内存。

 1 class Person
 2 {
 3 public:
 4     Person()
 5     {
 6         cout << "Person的默认构造函数调用" << endl;
 7     }
 8     Person(int age,int height)
 9     {
10         cout << "Person的有参构造函数调用" << endl;
11         m_Age = age;
12         m_Height = new int(height);
13     }
14     Person(const Person& p)
15     {
16         cout << "Person的拷贝构造函数调用" << endl;
17         m_Age = p.m_Age;
18         //当我们把拷贝构造函数注释掉的时候,编译器会自动进行以下程序,也就是说只要涉及到拷贝对象拷贝给被拷贝对象指针类型的成员函数的时候就是浅拷贝
19         //m_Height = p.m_Height;
20         //深拷贝操作
21         m_Height = new int(*p.m_Height);
22     }
23     ~Person()
24     {
25         //析构代码,将堆区开辟数据做释放操作
26         if (m_Height != NULL)
27         {
28             delete m_Height;
29             m_Height = NULL;
30             cout << "Person的析构函数调用" << endl;
31         }
32     }
33     int m_Age;
34     int* m_Height;
35 };
36 void test01()
37 {
38     Person p(18,168);
39     Person p2(p);
40     cout << "p的年龄为:" << p.m_Age << "身高为:" << *p.m_Height << endl;
41     cout << "p2的年龄为:" << p2.m_Age << "身高为:" << *p2.m_Height << endl;
42 }
43 int main()
44 {
45     test01();
46 }

 

标签:函数,对象,构造,拷贝,属性,基本概念,构造函数
From: https://www.cnblogs.com/Sandals-little/p/17398404.html

相关文章

  • 【Azure 存储服务】使用 AppendBlobClient 对象实现对Blob进行追加内容操作
    问题描述在AzureBlob的官方示例中,都是对文件进行上传到Blob操作,没有实现对已创建的Blob进行追加的操作。如果想要实现对一个文件的多次追加操作,每一次写入的时候,只传入新的内容? 问题解答AzureStorageBlob有三种类型:BlockBlob,AppendBlob和PageBlob。其中,只有AppendBlo......
  • Strng创建对象
    下面说的常量池都是指字符串常量池,字符串常量池存在运行时常量池之中(在JDK7之前存在运行时常量池之中,在JDK7已经将其转移到堆中),运行时常量池从永久代移到了元空间中。Stringa=newString("ab");此时创建了两个对象,常量池中创建了ab对象,堆内存中也创建了ab对象,此时引用指向堆......
  • 面向对象,面向对象的3个装饰器
    面向对象-断浪狂刀忆年少-博客园(cnblogs.com)通过函数实现面向对象编程面向对象的思维内涵只关心程序中有多少角色每个角色有什么方法,有什么属性所有角色都是由一个模板创建的所有属性和技能都待在自己的角色模板中--------可读性好能够更加方便得为角色添......
  • vue2中数组和对象更改后视图不刷新解决办法
    vue2中,改变集合或数据某值时有时候并不会自动更新到视图上去,解决办法  1、官方推荐例如:projectList数组,show值点击一次改变一次方向<tdv-on:click="alertSub(index)"><ahref="javascript:;">{{item.}}</a></td>alertSub(index){this.projectLi......
  • 9、对象
    内容来自王争Java编程之美1、......
  • Java | 一分钟掌握定时任务 | 1 - 基本概念
    作者:Mars酱声明:本文章由Mars酱原创,部分内容来源于网络,如有疑问请联系本人。转载:欢迎转载,转载前先请联系我!什么是定时任务定时任务就是在指定时间执行的一个或一串动作的行为。现实世界中,比如我们向自己心爱的女友送上祝福;给自己的好友送上祝福。那么,我们为了准时送祝福,会怎么做?当然......
  • Scanner对象
    1.Scanner对象用Scanner类来获取用户的输入:Scanners=newScanner(System.in);通过Scanner类的next()与nextLine()方法获取输入的字符串,再读取之前我们一般需要使用hasNext()与hasNextLine()判断是否还有输入的数据。输入helloworld,结果显示hello       输入hellow......
  • 面向对象特征三:多态性
    对象的多态性多态性,是面向对象中最重要的概念,在Java中的体现:对象的多态性:父类的引用指向子类的对象格式:(父类类型:指子类继承的父类类型,或者实现的接口类型)父类类型变量名=子类对象;举例Personp=newStudent();Objecto=newPerson();//Object类型的变量o,指向Person类......
  • Json序列化对象后,使用Lombok后属性xAxis大写变成小写xaxis解决方法
    一、问题描述最近在开发后端接口时,发现返回结构中,一个字段大小写转化有问题。lombok版本:1.18.14VO对象如下,字段为echarts趋势图组件。预期返回xAxis,实际返回xaxis@DatapublicclassULineBarVO{/***X轴信息*/privateULineBarDataVOxAxis;/*......
  • Optional对象的使用
    Optional是一个对象容器,具有以下两个特点:提示用户要注意该对象有可能为null简化ifelse代码1.创建:Optional.empty():创建一个空的Optional实例//返回一个Null的optionalOptionalempty=Optional.empty();Optional.of(Tt):创建一个Optional......