c++学习之类与对象2

news2024/11/24 5:51:27

目录

1.explicit关键字

类的对象数组

动态对象的创建与初始化

1.动态创建的概述

2.c语言方式创建动态对象

c++对象的动态申请

1.new创建动态对象

2.delete释放动态对象

动态对象数组

 静态成员

静态成员变量

静态成员函数


1.explicit关键字

explicit关键字 修饰构造函数 作用是不能通过隐式法调用构造函数。

首先我们先了解构造函数的隐式转换:

#include<iostream>
using namespace std;
class mystring
{
public:
	mystring(int n)
	{
		cout << "mysting(const char *str)" << endl;
	}
	mystring(const char* str)
	{
		cout << "mysting(conts char *str)"<<endl;
	}
};
int main()
{
	//给字符串赋值?还是初始化?
	mystring st1=1;//隐式构造函数
	//因为实例化对象要调动构造函数,而这里就会寻找构造函数其参数为整形的,而不是赋值
	//所以这是初始化
	mystring str2(10);//构造函数赋值,这里看比较显而易见

	//寓意非常明显,给字符串赋值
	mystring st3 = "abcd";
	mystring str4 = ("abcd");
	return 0;

}

我们发现有时候隐式的构造函数赋值时写法会与赋值这两种混淆含义,不清楚该操作是初始化构造函数还是给对象赋值,于是我们使用了一个关键字explicit,用来修饰构造函数不会有初始化是以上代码“mystring  str2=1”这种方式,这种方式只能是给认为给对象赋值。

explicit mystring(int n)
	{
		cout << "mysting(const char *str)" << endl;
	}

这样修饰构造函数之后,在这样写是无法找到对印的构造函数:

类的对象数组

本质上是一个数组,其成员为类的对象。

 举例:

class A
{
public:
	int a;//这里我们为了便于访问就直接定义为公有的
public:
	A()
	{
		a = 0;
		cout << "A的无参构造a=" << a << endl;
	}
	A(int x)
	{
		a = x;
		cout << "A的有参构造a=" << a << endl;
	}
	~A()
	{
		cout << "A的析构函数 a=" << a << endl;
	}
};
int main()
{
	//对象数组  每个元素都会自动调用构造函数和析构函数
	//对象数组不初始化  每个元素是调用无参构造的
	A arr1[5];


	//对象初始化时,必须显示使用有参构造  逐个元素初始化
	A arr2[5] = { A(10),A(20),A(30),A(40),A(50) };
	int n = sizeof(arr2) / sizeof(arr2[0]);
	int i = 0;
	for (i = 0; i < n; i++)
	{
		cout << arr2[i].a<<" " ;
	}
	cout << endl;
}

在这里,数组元素即类的对象的创建是遵循栈的规则,先创建后释放。

 

 我们可以观察构造函数调用与释放时的顺序。创建时先从前往后创建,释放时从后往前释放。

动态对象的创建与初始化

1.动态创建的概述

当我们创建数组的时候,总需要提前预定数组长度,然后编译器分配预定长度的数组空间。但我们学了c语言就知道,在不知道的数组大小前提下,给定空间可能太大,浪费空间,可能太小,空间不够用。而动态创建专门解决这类问题,在c语言中提供专门开辟空间的函数malloc  realloc,calloc结合释放空间的函数free是现在堆区上动态开辟空间,需要多少,开辟多少。

2.c语言方式创建动态对象

当创建一个c++对象时会发生两件事:

1.为对象分配内存

2.调用构造函数初始化那片内存空间。

而第二步时确保一定能发生的。c++强迫我们必须要这样做是因为使用未初始化的对象是程序报错的重要原因。在c语言中提供专门开辟空间的函数malloc  realloc,calloc,这些函数式时能有效开辟空间的,但是原始的,需要我们小心谨慎的使用。

举例:利用c动态开辟的的方式

class person
	 {
 public:
	 person()
		 {
		 cout << "person无参构造" << endl;
		 }
	 ~person()
		 {
		 cout << "person析构" << endl;
		 }
	 int a;
	
		 };
 void test01()
 {
	 person * p = (person*)malloc(sizeof(person));
//判断是否开辟成功
//调用初始化函数
//清理对象
	 free(p);
	 }
int main()
 {
	 test01();
	 return 0;
 }

注意:malloc和free动态申请对象和释放对象 使用malloc和free函数去动态申请对象,和释放申请的对象时不会调用构造函数和析构函数。但是我们同样我们需要自己去调用初始化函数和清理对象的函数。

我们可以看到这是对于c++来说是,反其道而行之,我们必须自己去初始化,并清理。

出现的问题有:

1.程序员必须确定对象长度

2.malloc时返回一个void的指针,在c++中是不允许将void型的赋值给其他指针

3.malloc可能会申请内存失败

4.用户在使用对象前必须亲自初始化,之后亲自清理。

c的动态申请太复杂,我们在c++中不适用。

c++对象的动态申请

1.new创建动态对象

c++中解决动态分配的方案是把创建的一个对象所需的操作都结合在一个称为new的运算符中,当用new创建一个对象时,它就在堆区为对象分配所需的空间并完成初始化。如下:

person *person=new person;

 

new操作符能确定再调用构造函数初始化前内存分配时成功的,所以不用显示是否调用成功。因此在队里创建对象的过程变得更简单了。

2.delete释放动态对象

new的对头时delete,delete先调用析构函数,然后释放内存。

举例:

class person
{
public:
	person()
	{
		cout<<"无参构造函数!"<<endl;
		pname = new char[strlen("undefined") + 1];
		strcpy(pname, "undefined");
		page = 0;
	}
	person( char *arr,int x)
	{
		cout << "有参构造函数!" << endl;
	    pname = new char[strlen(arr) + 1];
	    strcpy(pname, arr);
		page = x;
	}
	void showperson()
	{
		cout << "name:" << pname << "age:" << page << endl;
	}
	~person()
	{
		cout << "调用了析构函数" << endl;
		if (pname != NULL)
		{
			delete[]pname;
			pname = NULL;
		}
	}
	//这里为了方便调用还是用公共型的
public:
	char* pname;
	int page;
};
int main()
{
	person* person1 = new person;//自动调用无参构造
	person* person2 = new person((char *)"john", 33);//自动调用有参构造
	person1->showperson();
	person2 -> showperson();
	delete person1;
	delete person2;

}

动态对象数组

所创建的的对象数组为动态开辟,举例

class person
{
public:
	person()
	{
		pname = NULL;
		page = 0;
	}
	person(char* name, int age)
	{
		pname = new char[strlen(name) + 1];
		strcpy(pname, name);
		page = age;
	}
	~person()
	{
		if (pname != NULL)
		{
			delete []pname;
			pname = NULL;
		}
	}
public:
	char* pname;
	int page;
};
void test()
{
	//栈聚合初始化
	person sperson[] = { person((char*)"john",12),person((char*)"marke",14) };
	cout << sperson[1].pname << endl;
	//创建堆上的数组对象必须提供构造函数
	person* workers = new person[20];
	delete []workers;
}

可以看到new与delete 是成对出现的,注意他们的使用方法:

类型 *p = new 类型;

delete p; 申请数组:

类型 *p = new 类型[n];

delete [ ]p;

 

 静态成员

在类定义中,它的成员(包括成员变量和成员函数),这些成员可以用 关键字static声明为静态的,称为静态成员。 不管这个类创建了多少个对象,静态成员只有一个拷贝,这个拷贝被所 有属于这个类的对象共享。

静态成员变量

static修饰的静态成员是属于类的,而不是对象

静态成员变量在内存中只有一份

多个对象共享一个静态变量 静态成员变量

必须类内声明,类外定义 静态成员变量可以通过类的作用域访问

静态成员变量可以通过类的对象访问

static 修饰的成员,定义类的时候,必须分配空间(在编译阶段)。

 举例:

class person
{
 public:
	 int a;//普通变量
	 //静态成员变量不能再类内初始化 类内只能声明,定义在全局 声明的作用只是限制静态
	 //成员变量作用域
	 static int b;//静态成员变量 在编译阶段就分配内存 存在静态全局区
 };
int person::b = 10;//类中成员变量的定义
 void test01()
{
	 person p1;
	 p1.b = 100;
	 cout << p1.b << endl;
	
 }
 void test02()
 {
	 cout << person::b << endl;//通过类的作用域访问类的静态成员函数,无需再今经过对象
	//cout << person::a << endl;
		
 }

 using namespace std;
 int main()
 {
    test01();
	test02();
	return 0;
 }

可以看到静态修饰后,它可以通过外部修改。 

静态成员函数

跟静态成员变量一样,是直属于类的,直接通过类访问问。

.静态成员函数能访问静态成员变量不能访问普通的成员变量

.可以通过类的作用域访问静态成员函数

.可以通过对象访问静态成员函数

与静态变量不一样,变量在类之前就已经定义好了(外部定义)。但函数可以直接在内部定义。

举例:

class person
	 {
public:
	 int a;
	 //静态成员变量不能再类内初始化 类内只能声明,定义在全局 声明的作用只是限制静态
	 //成员变量作用域
     static int b;//静态成员变量 在编译阶段就分配内存 存在静态全局区
	 void show()
		 {
		 cout << a << " " << b << endl;;
		 }
	 static void static_show()//静态成员函数 可以访问静态成员变量 不能访问普通的
		//成员变量
		 {
		 cout << " " << b << endl;;
		 }
	
	 };
int person::b = 100;
 void test01()
 {
	 person::static_show();//通过流类的作用域访问静态成员函数
	 person p1;
	 p1.static_show();//通过对象访问静态成员函数
	
}
 int main()
 {
	 test01();
	 return 0;
 }

值得注意的是,静态成员函数只能操作静态成员变量,对普通的变量的无法操作。

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

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

相关文章

查询淘宝商品详情页面数据(商品详情数据,商品销量数据,商品sku数据,商品视频数据,商品优惠券数据)接口代码封装教程

业务场景&#xff1a;作为全球最大的 B2C 电子商务平台之一&#xff0c;淘宝天猫平台提供了丰富的商品资源&#xff0c;吸引了大量的全球买家和卖家。为了方便开发者接入淘宝天猫平台&#xff0c;淘宝天猫平台提供了丰富的 API 接口&#xff0c;其中历史价格接口是非常重要的一…

策略设计模式(Strategy Pattern)[论点:概念、组成角色、相关图示、示例代码、适用场景]

文章目录概念组成角色相关图示示例代码适用场景概念 策略模式&#xff08;Strategy Pattern&#xff09;是一种行为设计模式&#xff0c;它定义了一系列的算法&#xff0c;并将每一个算法封装起来&#xff0c;使它们可以相互替换。策略模式使得算法可以独立于使用它的客户端变化…

4.12~4.13学习总结

File 相对路径和绝对路径的区别&#xff1a; 相对路径不带盘符&#xff0c;绝对路径带盘符 小知识点&#xff1a;1KB1024字节&#xff0c;1MB1024KB,1GB1024MB; File对象就表示一个路径&#xff0c;可也是文件的路径&#xff0c;也可以是文件夹的路径 这个路径可以是存在的也可…

API-MS-WIN-CRT-RUNTIME-L1-1-0.DLL丢失怎么解决?

API-MS-WIN-CRT-RUNTIME-L1-1-0.DLL是Windows系统中的一个非常重要的动态链接库文件&#xff0c;该文件的全称为“Application Programming Interface Microsoft Windows C Runtime Link Library”。这个DLL文件中包含多个函数库&#xff0c;可将这些函数库链接到应用程序中。在…

AC7811-FOC无感控制代码详解

目录 矢量控制原理 矢量控制框图 电流采样方式 电流在整个控制过程中的传递 采样关键点 三电阻 双电阻 单电阻 三者对比 坐标变换 dq轴电流的PI控制 启动方式 启动波形 脉冲注入 高频注入 Startup 预定位到指定角度 PulseInject_api hfi_api Speed loop s…

已解决:ModuleNotFoundError: No module named ‘flask._compat‘

📋 个人简介 💖 作者简介:大家好,我是阿牛,全栈领域新星创作者。😜🎉 支持我:点赞👍+收藏⭐️+留言📝📣 系列专栏:flask框架从入门到实战🍁💬格言:要成为光,因为有怕黑的人!🔥 相信很多人在flask项目中都遇到了这个报错:ModuleNotFoundError: No …

MyBatis动态SQL的使用

为什么需要使用动态sql? 在实际项目的开发中&#xff0c;开发人员在使用JDBC或其他持久层框架进行开发时&#xff0c;经常需要根据不同的条件拼接SQL语句&#xff0c;拼接SQL语句时还要确保不能遗漏必要的空格、标点符号等&#xff0c;这种编程方式给开发人员带来了非常大的不…

初探JdbcTemplate操作

文章目录一、创建数据库二、创建用户三、打开Spring项目四、添加数据库相关依赖五、创建用户实体类六、创建用户数据访问接口七、创建用户数据访问接口实现类八、创建用户服务类九、创建数据库配置属性文件十、创建Spring配置文件十一、创建用户服务测试类1、测试按编号查询用户…

Java 管道 (学习代码)

目录 上代码&#xff1a; 输出&#xff1a; 执行流程可以总结如下&#xff1a; 上代码&#xff1a; package cn.net.cdsz.ccb.test;import java.io.IOException; import java.io.PipedReader; import java.io.PipedWriter;public class test {static class ReaderThread imp…

C++回溯算法---图的m着色问题01

C回溯算法---图的m着色问题 图的m着色问题是指给定一个图以及m种不同的颜色&#xff0c;尝试将每个节点涂上其中一种颜色&#xff0c;使得相邻的节点颜色不相同。这个问题可以转化为在解空间树中寻找可行解的问题&#xff0c;其中每个分支结点都有m个儿子结点&#xff0c;最底层…

Flink、Hudi技术选型

Flink CDC 2.2的优势 相比Flink1.x&#xff0c;2.x的版本有如下的特点&#xff1a; 1) 并发读取&#xff0c;全量数据的读取性能可以水平扩展。 2) 全程无锁&#xff0c;不对线上业务产生锁的风险。 3) 断点续传&#xff0c;支持全量阶段的 Checkpoint。 Flink SQL的优势 …

MongoDB学习

文章目录前言0 MongoDB和Redis区别1 简介MongoDB2 MongoDB的安装(需要使用Docker)3 MongoDB 概念解析3.1 数据库3 .2 文档3.3 集合3.4 MongoDB 数据类型3.5适用场景4 常用操作4.1 INSERT4.2 Query4.3 Update4.4 Remove4.5 aggregate4.6 索引5 整合Springboot使用5.1 导入依赖5.…

多比特信号跨时钟域同步处理

多比特信号跨时钟域同步处理 当在时钟域之间传递多比特数据时&#xff0c;普通的同步器并不能保证数据传递的安全性。在多时钟设计中&#xff0c;工程师往往容易犯一个错误&#xff0c;即同一事务处理含有需要从一个时钟域向另一个时钟域传递的多位跨时钟数据,并忽略了同步采样…

腾讯云物联网开发平台 LoRaWAN 透传接入 更新版

前言 之前有一篇文章介绍LoRaWAN透传数据&#xff0c;不过还是用物模型云端数据解析脚本&#xff0c;不是真正的透传。腾讯云物联网开发平台也支持对LoRaWAN原始数据的透传、转发。今天来介绍下。腾讯云 IoT Explorer 是腾讯云主推的一站式物联网开发平台&#xff0c;IoT 小能手…

大话数据结构-C(1)

一&#xff1a;数据结构绪论 1.1 数据&#xff1a; 描述客观事物的符号&#xff0c;计算机中可以操作的对象&#xff0c;能被计算机识别并输入给计算机处理的符号集合。 1.2 数据元素 是组成数据的、有一定意义的基本单位&#xff0c;在计算机中通常作为整体处理。也被称为记…

Linux系统如何设置开机自启脚本

Linux系统开启自启脚本的配置&#xff0c;我这里记录了三种办法&#xff0c;对于绝大多数linux系统&#xff0c;这三种方法里肯定有合适的。 1. 设置/etc/rc.local文件 /etc/rc.local文件是 /etc/rc.d/rc.local文件的软连接&#xff0c;rc.local文件本质上就是一个shell脚本 …

电商TO B背后:谁在重构产业带?

在这盘产业带大旗里&#xff0c;京东、淘宝、拼多多正在成为鲜活的新注解。 作者|思杭 编辑|皮爷 出品|产业家 有一座城&#xff0c;这里的百姓在40年前靠“鸡毛换糖”起家&#xff0c;他们聚集了全国各地的商品&#xff0c;再转卖出去。这样一来&#xff0c;就形成了销路…

金三银四最近一次面试,被阿里P8测开虐惨了.....

都说金三银四涨薪季&#xff0c;我是着急忙慌的准备简历——5年软件测试经验&#xff0c;可独立测试大型产品项目&#xff0c;熟悉项目测试流程...薪资要求&#xff1f;5年测试经验起码能要个20K吧 我加班肝了一页半简历&#xff0c;投出去一周&#xff0c;面试电话倒是不少&a…

itop-3568开发板驱动学习笔记(17)内核中断

《【北京迅为】itop-3568开发板驱动开发指南.pdf》 学习笔记 文章目录中断基础中断中断上下文中断号中断源类型内核中断 API获取中断号中断申请释放中断禁止中断使能中断实验程序中断基础 中断 CPU 在正常运行期间&#xff0c;由外部或者内部引起的事件&#xff0c;让 CPU 停下…

研报精选230411

目录 【行业230411华安证券】智能家居行业深度&#xff1a;ChatGPT等大模型催化智能家居行业进一步发展【行业230411信达证券】食品饮料行业2023年第12周周报&#xff1a;从当前时间点看今年液奶的投资机会【行业230411东方财富证券】食品饮料行业专题研究&#xff1a;BC两端需…