【第二天】C++类和对象解析:构造函数、析构函数和拷贝构造函数的完全指南

一、类的引出概述

        在c语言结构体中,行为和属性是分开的,万一调用错误,将会导致问题发生。c++中类将数据方法封装在一起,加以权限区分,用户只能通过公共方法 访问 私有数据

二、封装

        封装特性包含两个方面,一个是属性和变量合成一个整体,一个是给属性和函数增加访问权限

1.把变量(属性)和函数(操作)合成一个整体,封装在一个类中

2.对变量和函数进行访问控制访问权限
3.在类的内部(作用域范围内),没有访问权限之分,所有成员可以相互访问

4.在类的外部(作用域范围外),访问权限才有意义:.public、private、protected

5.在类的外部,只有public.修饰的成员太能被访问,在没有涉及继承与派生时,private和protected是相同等级的.外部不允许访问        

访问属性属性对象内部对象外部
public公有可访问可访问
private保护可访问不可访问
protected私有可访问不可访问

尽量设置成员变量为私有权限,将方法设置成公有。

优点:

对变量的设置时的控制

实现变量设置只读权限

实现变量设置只写权限

实现变量设置可读可写权限

struct和class的区别:class默认访问权限为.private,struct默认访问权限为public.

三、类的案例(了解)

1、设计一个person类

        设计一个Person类,Person类具有name和age属性,提供初始化函数(Init),并提供对name和age 的读写函数(set,get),但必须确保age的赋值在有效范围内(0-100),超出有效范围,则拒绝赋值,并 提供方法输出姓名和年龄。----需要六个函数

#include <iostream>
using namespace std;
#include<string.h>
class Person
{
private:char mName[32];int mAge;
public://初始化成员void init(char *name, int age){strcpy(mName, name);if(age>=0 && age<=100){mAge = age;}else{cout<<"年龄无效"<<endl;}return;}//设置namevoid setName(char *name){strcpy(mName, name);}//获取namechar *getName(void){return mName;}//设置agevoid setAge(int age){if(age>=0 && age<=100){mAge = age;}else{cout<<"年龄无效"<<endl;}}//得到ageint getAge(void){return mAge;}//显示所有数据void showPerson(void){cout<<mName<<" "<<mAge<<endl;}
};
void test02()
{Person ob1;ob1.init("lucy", 18);ob1.showPerson();ob1.setName("bob");cout<<"年龄:"<<ob1.getAge()<<endl;ob1.showPerson();
}

2、设计一个立方体类

        设计立方体类(Cube),求出立方体的面积( 2ab +2ac +2bc )和体积( a*b*c),分别用全局函数和成员函数判断两个立方体是否相等。

class Cube
{
private:int mA;int mB;int mC;public:void setA(int a){mA = a;}int getA(void){return mA;}void setB(int b){mB = b;}int getB(void){return mB;}void setC(int c){mC = c;}int getC(void){return mC;}//获取面积int getS(void){return (mA*mB+mB*mC+mC*mA)*2;}//获取体积int getV(void){return mA*mB*mC;}//成员函数 比较两个立方体是否先等bool compareCube01(Cube &ob){if(mA==ob.mA && mB ==ob.mB && mC == ob.mC){return true;}return false;}
};//全局函数 比较两个立方体是否先等
bool compareCube02(Cube &ob1, Cube &ob2)
{if(ob1.getA()==ob2.getA() && ob1.getB() ==ob2.getB() && ob1.getC() == ob2.getC()){return true;}return false;
}void test()
{Cube ob1;ob1.setA(10);ob1.setB(20);ob1.setC(30);cout<<"面积:"<<ob1.getS()<<endl;cout<<"体积:"<<ob1.getV()<<endl;Cube ob2;ob2.setA(10);ob2.setB(20);ob2.setC(30);// if(compareCube02(ob1, ob2))if(ob1.compareCube01(ob2)){cout<<"相等"<<endl;}else{cout<<"不相等"<<endl;}
}
int main(int argc, char *argv[])
{test();return 0;
}

3、点和圆的关系

        设计一个圆形类(AdvCircle),和一个点类(Point),计算点和圆的关系。

class Point
{
private:int mX;int mY;
public:void setX(int x){mX = x;}int getX(void){return mX;}void setY(int y){mY = y;}int getY(void){return mY;}
};
class Circle
{
private:Point p;//对象作为类的成员变量int mR;
public:void setPoint(int x, int y){p.setX(x);p.setY(y);}Point getPoint(void)//打印圆点{return p;}void setR(int r){mR = r;}int getR(void){return mR;}//判断点 在圆的位置int pointIsOnCircle(Point &ob){int len = (ob.getX()-p.getX())*(ob.getX()-p.getX())+\(ob.getY()-p.getY())*(ob.getY()-p.getY());if(len == mR*mR){return 0;}else if(len > mR*mR){return 1;}else if(len < mR*mR){return -1;}}
};
void test()
{
//实例化一个点的对象Point p;p.setX(5);p.setY(5);//实例化一个圆的对象Circle cir;cir.setPoint(2,2);cir.setR(5);if(cir.pointIsOnCircle(p) == 0){cout<<"点在圆上"<<endl;}else if(cir.pointIsOnCircle(p) > 0){cout<<"点在圆外"<<endl;}else if(cir.pointIsOnCircle(p) < 0){cout<<"点在圆内"<<endl;}
}

4、类中成员函数在类外实现

5、类在其他文件实现

        头文件定义类, cpp实现类的成员函数

data.h

#ifndef DATA_H
#define DATA_H
class Data
{
private:int mA;
public:int getA(void);void setA(int a);
};
#endif 

 data.cpp

#include "data.h"
int Data::getA()
{return mA;
}
void Data::setA(int a)
{mA = a;
}

main.cpp

#include <iostream>
#include "data.h"
using namespace std;
int main(int argc, char *argv[])
{Data ob;ob.setA(100);cout<<ob.getA()<<endl;return 0;
}

对象的构造和析构:

        当我们创建对象的时候,这个对象应该有一个初始状态,当对象销毁之前应该销毁自己创建的一些数据。对象的初始化清理也是两个非常重要的安全问题,C++为了给我们提供这种问题的解决方案,构造函数和析构函数,这两个函数将会被编译器自动调用完成对象初始化(创建对象时为对象成员属性赋值)和对象清理工作。初始化和清理工作是编译器强制我们要做的事情,即使你不提供初始化操作和清理操作,编译器也会给你增加默认的操作,只是这个默认初始化操作不会做任何事。

四、构造函数(初始化工作)

1、概述

        构造函数是类实例化对象时自动调用

2、创建

        构造函数名与类名称相同,不能有返回值类型(连void都不可以),可以有参数(支持重载),必须加public权限。

3、分类

        无参构造、有参构造。

4、调用

        类实例化对象时:先为对象开辟空间 然后才调用构造函数。 

1、如果用户不提供构造函数 编译器会自动 提供一个无参空的构造函数。

2、如果用户提供构造函数 编译器会自动 屏蔽默认无参的构造

四种:隐式调用、显示调用、隐式转换、匿名调用 

注:写任何一个类 无参构造, 有参构造都需要实现 

5、explicit关键字防止构造函数隐式转换

        explicit修饰构造函数,防止构造函数隐式转换,避免令人产生赋值误会。

允许隐式转换:

//此时允许有参构造隐式转换
A(int a)
{mA = a;cout<<"A的有参构造mA="<<mA<<endl;
}
//构造函数隐式转换(类中只有一个数据成员)
A ob1=100;//ok

不允许隐式转换:

//防止有参构造 隐式转换
explicit A(int a)
{mA = a;cout<<"A的有参构造mA="<<mA<<endl;
}
//构造函数隐式转换(类中只有一个数据成员)
A ob1=100;//err 转换失败

五、析构函数(清理工作)

         当对象生命周期结束的时候 系统自动调用析构函数。

        函数名和类名称相同,在函数名前加~,没有返回值类型,没有函数形参。(不能被重载) 先调用析构函数 再释放对象的空间。

调用释放顺序:括号内的最先释放,释放先进后出

         一般情况下,空的析构函数就足够。但是如果一个类有指针成员,这个类必须 写析构函数,释放指针成员所指向空间。

#include<iostream>
#include<stdlib.h>
#include<string.h>
using namespace std;
class Data
{
public:char *name;
public:Data(){name = NULL;}Data(char *str){name = (char*)calloc(1, strlen(str) + 1);strcpy(name, str);cout << "有参构造 name=" << name << endl;}~Data(){cout << "析构函数" <<name<< endl;if (name != NULL){free(name);name = NULL;}}};
void test()
{	Data ob("hello world");
}

六、拷贝构造函数

1、定义

        拷贝构造函数本质是构造函数

        拷贝构造的调用时机:对象 初始化 对象 时。

 如果用户不提供拷贝构造 编译器会自动提供一个默认的拷贝构造(完成赋值动作--浅拷贝)

2、拷贝构造 和 无参构造 有参构造的关系

如果用户定义了 拷贝构造或者有参构造 都会屏蔽无参构造。

如果用户定义了 无参构造或者有参构造 不会屏蔽拷贝构造。

3、拷贝构造调用形式

(1)旧对象给新对象初始化 调用拷贝构造

Data ob1(10);
Data ob2 = ob1;//调用拷贝构造

(2)普通对象作为函数参数 调用函数时 会发生拷贝构造 

(3)函数返回值普通对象 (Visual Studio会发生拷贝构造) 

Data get(void)
{Data ob1(10);return ob1;
}
void test()
{	Data ob2 = get();
}

注:给对象取别名 不会调用拷贝构造 

Data ob1(10);
Data &ob2 = ob1;//不会调用拷贝构造

4、拷贝构造中浅拷贝和深拷贝

        如果类中没有指针成员, 不用实现拷贝构造和析构函数。

        如果类中指针成员和拷贝构造调用, 必须实现析构函数释放指针成员指向的堆区空间,必须实现拷贝构造完成深拷贝动作(因拷贝构造释放时相应堆区空间需再释放一次,故堆区空间也需重新拷贝一次)

 七、初始化列表

成员对象:一个类的对象 作为另一个类的成员

类会自动调用成员对象的无参构造,如果类中想调用成员对象有参构造 必须使用初始化列表

class A
{
public:int mA;
public:A(){mA = 0;cout << "A的无参构造" << endl;}A(int a){mA = a;cout << "A的有参构造" << endl;}~A(){cout << "A的析构函数" << endl;}
};
class B
{
public:int mB;A ob;//成员对象
public:B(){cout << "B类的无参构造" << endl;}//初始化列表 成员对象 必须使用对象名+() 重要B(int a, int b) :ob(a){mB = b;cout << "B类的有参构造" << endl;}~B(){cout << "B的析构函数" << endl;}};
int main(int argc, char* argv[])
{B ob1(10, 20);cout << "mA =" << ob1.ob.mA << ", mB =" << ob1.mB << endl;return 0;}

 八、对象数组

        对象数组:本质是数组 数组的每个元素是对象

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

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

相关文章

【C++】-c++的类型转换

&#x1f496;作者&#xff1a;小树苗渴望变成参天大树&#x1f388; &#x1f389;作者宣言&#xff1a;认真写好每一篇博客&#x1f4a4; &#x1f38a;作者gitee:gitee✨ &#x1f49e;作者专栏&#xff1a;C语言,数据结构初阶,Linux,C 动态规划算法&#x1f384; 如 果 你 …

自然语言处理---Self Attention自注意力机制

Self-attention介绍 Self-attention是一种特殊的attention&#xff0c;是应用在transformer中最重要的结构之一。attention机制&#xff0c;它能够帮助找到子序列和全局的attention的关系&#xff0c;也就是找到权重值wi。Self-attention相对于attention的变化&#xff0c;其实…

使用vscode搭建虚拟机

首先vscode插件安装 名称: Remote - SSH ID: ms-vscode-remote.remote-ssh 说明: Open any folder on a remote machine using SSH and take advantage of VS Codes full feature set. 版本: 0.51.0 VS Marketplace 链接: https://marketplace.visualstudio.com/items?it…

黑豹程序员-架构师学习路线图-百科:MVC的演变终点SpringMVC

MVC发展史 在我们开发小型项目时&#xff0c;我们代码是混杂在一起的&#xff0c;术语称为紧耦合。 如最终写ASP、PHP。里面既包括服务器端代码&#xff0c;数据库操作的代码&#xff0c;又包括前端页面代码、HTML展现的代码、CSS美化的代码、JS交互的代码。可以看到早期编程就…

基于SSM的快递管理系统设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

proteus中仿真arduino的水位测试传感器

一、原理介绍 我们这里使用的水位传感器&#xff0c;只能说是一个小实验用途的水位传感器。我们首先上图 如上图所示&#xff0c;线没有连接&#xff0c;传感器由许5对裸露在外的铜线片作为传感部分&#xff0c;当浸入水中时这些铜线片会被水桥接。 这些被水连接起来的铜线&a…

【NPM】vuex 数据持久化库 vuex-persistedstate

在 GitHub 上找到&#xff1a;vuex-persistedstate。 安装 npm install --save vuex-persistedstate使用 import { createStore } from "vuex"; import createPersistedState from "vuex-persistedstate";const store createStore({// ...plugins: [cr…

android studio打开flutter项目报红

一、android studio打开flutter项目报红&#xff0c;如下图&#xff1a; 二、解决方法&#xff1a; 2.1 在这个build.gradle添加以下代码&#xff0c;如图&#xff1a; 2.2 在build.gradle最顶部添加如下代码&#xff1a; def localProperties new Properties() def localPr…

基于指数分布优化的BP神经网络(分类应用) - 附代码

基于指数分布优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码 文章目录 基于指数分布优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码1.鸢尾花iris数据介绍2.数据集整理3.指数分布优化BP神经网络3.1 BP神经网络参数设置3.2 指数分布算法应用 4.测试结果…

STM32不使用 cubeMX实现外部中断

这篇文章将介绍如何不使用 cubeMX完成外部中断的配置和实现。 文章目录 前言一、文件加入工程二、代码解析exti.cexti.hmain.c 注意&#xff1a;总结 前言 实验开发板&#xff1a;STM32F103C8T6。所需软件&#xff1a;keil5 &#xff0c; cubeMX 。实验目的&#xff1a;如何不…

AdaBoost:增强机器学习的力量

一、介绍 机器学习已成为现代技术的基石&#xff0c;为从推荐系统到自动驾驶汽车的一切提供动力。在众多机器学习算法中&#xff0c;AdaBoost&#xff08;自适应增强的缩写&#xff09;作为一种强大的集成方法脱颖而出&#xff0c;为该领域的成功做出了重大贡献。AdaBoost 是一…

面试题:谈谈过滤器和拦截器的区别?

文章目录 一、拦截器和过滤器的区别二、拦截器和过滤器的代码实现1、拦截器2、过滤器 三、总结1、什么是Filter及其作用介绍2、Filter API介绍3、Filter链与Filter生命周期 四、拦截器五、过滤器和拦截器的区别 一、拦截器和过滤器的区别 1、拦截器(Interceptor)只对action请求…

【鸿蒙软件开发】ArkTS常见组件之单选框Radio和切换按钮Toggle

文章目录 前言一、Radio单选框1.1 创建单选框1.2 添加Radio事件1.3 场景示例二、切换按钮Toggle2.1 创建切换按钮2.2 创建有子组件的Toggle2.3 自定义样式selectedColor属性switchPointColor属性 2.4 添加事件2.5 示例代码 总结 前言 Radio是单选框组件&#xff0c;通常用于提…

SpringCloud之gateway基本使用解读

目录 基本介绍 概述 API网关介绍 路由&#xff08;Route&#xff09; 断言&#xff08;Predicate&#xff09; 过滤器&#xff08;Filter&#xff09; 简单JAVA代码实战 实战架构 teacherservice服务 gateway服务 测试 断言工厂 过滤器工厂 全局过滤器 &#xf…

前端导出数据到Excel(Excel.js导出数据)

库&#xff1a;Excel.js&#xff08;版本4.3.0&#xff09; 和 FileSaver&#xff08;版本2.0.5&#xff09; CDN地址&#xff1a; <script src"https://cdn.bootcdn.net/ajax/libs/exceljs/4.3.0/exceljs.min.js"></script> <script src"http…

什么是SpringMVC?简单好理解!

1、SpringMVC是什么&#xff1f; SpringMVC是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级web框架&#xff0c;通过把Model&#xff0c;View&#xff0c;Controller分离&#xff0c;将web层进行职责解耦&#xff0c;把复杂的web应用分成逻辑清晰的几部分。简化开发&…

UE5场景逐渐变亮问题

1、显示 -- 关闭眼部适应 2、项目设置 -- 关闭自动曝光 参考&#xff1a; 虚幻5/UE5 场景亮度逐渐变亮完美解决方法 - 哔哩哔哩

专业修图软件 Affinity Photo 2 mac中文版编辑功能

Affinity Photo for Mac是应用在MacOS上的专业修图软件&#xff0c;支持多种文件格式&#xff0c;包括psD、PDF、SVG、Eps、TIFF、JPEG等。 Affinity Photo mac提供了许多高级图像编辑功能&#xff0c;如无限制的图层、非破坏性操作、高级的选择工具、高级的调整层、HDR合成、全…

使用 PyAudio、语音识别、pyttsx3 和 SerpApi 构建简单的基于 CLI 的语音助手

德米特里祖布☀️ 一、介绍 正如您从标题中看到的&#xff0c;这是一个演示项目&#xff0c;显示了一个非常基本的语音助手脚本&#xff0c;可以根据 Google 搜索结果在终端中回答您的问题。 您可以在 GitHub 存储库中找到完整代码&#xff1a;dimitryzub/serpapi-demo-project…

RT-Thread学习笔记(四):RT-Thread Studio工具使用

RT-Thread Studio工具使用 官网详细资料实用操作1. 查看 RT-Thread RTOS API 文档2.打开已创建的工程3.添加头文件路径4. 如何设置生成hex文件5.新建工程 官网详细资料 RT-Thread Studio 用户手册 实用操作 1. 查看 RT-Thread RTOS API 文档 2.打开已创建的工程 如果打开项目…