浅谈C++|类的成员

news2024/12/24 21:49:22

一.类对象作为类成员

类可以作为另一个类的成员

代码: 

#include <iostream>
using namespace std;
class phone {
public:
	string shouji;
	phone(string shouji1) :shouji(shouji1) {
		cout << "phone的构造函数调用" << endl;
	}
	~phone() {
		cout << "phone的析构函数调用" << endl;
	}
};
class person {
public:
	int age;
	string name;
	phone shouji;
	//隐式转换相当于shouji=phone(shouji1)
	person(int a, string name1, string shouji1) :age(a), name(name1), shouji(shouji1) {
		cout << "person的构造函数调用" << endl;
	}
	~person() {
		cout << "person的析构函数调用" << endl;
	}
};
void fun() {
	person p(23, "小明", "苹果");
}
int main() {
	fun();
	return 0;
}

 注意:

创建类时,被包含的类的构造函数先调用,随后外层类的构造函数再调用,析构1的时候正好相反,外部类先析构,内部类再析构。

二.静态成员 

静态成员就是在成员变量前面加上static关键字,称为静态成员。

静态成员分为静态成员变量静态成员函数

2.1静态成员变量

。所有对象共享同一份数据

。在编译阶段分配内存。

类内声明,类外初始化·静态成员函数

 静态成员必须在类外初始化,否则编译器认为只声明,但是没有实际定义,链接发生错误。

代码: 

#include <iostream>
using namespace std;
class person {
public:
	static int age;
};
int person::age = 10;
void fun() {
	person p;
	p.age = 90;
	person p1;
	cout << p1.age << endl;
}
int main() {
	fun();
	return 0;
}

 静态成员变量,不仅可以通过对象访问,也可以通过类名访问。静态成员变量也是有访问权限的。

代码: 

#include <iostream>
using namespace std;
class person {
public:
	static int age;
};
int person::age = 10;
void fun() {
	person p;
	p.age = 90;
	cout << person::age << endl;
}
int main() {
	fun();
	return 0;
}

2.2静态成员函数

。所有对象共享同一个函数

静态成员函数只能访问静态成员变量

代码: 

#include <iostream>
using namespace std;
class person {
public:
	static int age;
	static void fun(int a) {
		age = a;          //只能调用静态成员变量
		cout << "静态函数fun调用" << endl;
	}
};
int person::age = 100;
void dioayong() {
	person p;
	p.fun(99);          //对象调用
	person::fun(66);   //类名调用
	cout << p.age << endl;
}
int main() {
	dioayong();
	return 0;
}

同样,静态成员函数也是可以通过类名来调用,需要注意静态成员函数只能调用静态成员变量。

 三.this指针

3.1成员变量和函数的存储

在C++中,类内的的成员变量和成员函数分开存储

只有非静态成员变量才属于类的对象上

在C++中, 空类也占用一个字节。C++编译器会给每个空对象也分配一个字节空间,是为了区分对象占内存的位置

代码: 

#include <iostream>
using namespace std;
class person {

};
void fun() {
	person p;
	cout<<sizeof(p);
}
int main() {
	fun();
	return 0;
}

 在类中同样具有内存对齐的特性

代码: 

#include <iostream>
using namespace std;
class person {
public:
	int a;
	char b;
};
void fun() {
	person p;
	cout<<sizeof(p);
}
int main() {
	fun();
	return 0;
}

 此外,成员函数和静态成员变量都不存储在类上,也就是只有非静态成员变量存储在类中

代码: 

#include <iostream>
using namespace std;
class person {
public:
	int a;
	static int b;
	void fun() {
		cout << "fun函数调用" << endl;
	}
	static void fun1() {
		cout << "fun1函数调用" << endl;
	}
};
int person::b = 10;
void fun() {
	person p;
	cout<<sizeof(p);
}
int main() {
	fun();
	return 0;
}

 3.2this指针使用

每一个非静态成员函数只会诞生一份函数实例,也就是说多个同类型的对象会共用一块代码那么问题是:这一块代码是如何区分那个对象调用自己的呢?

C++通过提供特殊的对象指针,this指针,解决上述问题。this指针指向被调用的成员函数所属的对象

 注意:

1.this指针是隐含每一个非静态成员函教内的一种指针

2.this指针不需要定义,直接使用即可

this指针的用途: 

·当形参和成员变量同名时,可用this指针来区分同名形参和变量

·在类的非静态成员函数中返回对象本身,可使用return *this

 代码:

#include <iostream>
using namespace std;
class people {
public:
	int age;
	people(int age) {
		this->age = age;
	}
};
void zhixing() {
	people p(10);
	cout << p.age << endl;
}
int main() {
	zhixing();
	return 0;
}

返回自身时,注意要返回引用类型,返回普通值类型时,返回值是本身的副本

#include <iostream>
using namespace std;
class people {
public:
	int age;
	people(int age) {
		this->age = age;
	}
	 people& add(const people& p) {
		this->age += p.age;
		return *this;
	}
};
void zhixing() {
	people p1(10);
	people p2(20);
	p2.add(p1).add(p1).add(p1).add(p1);
	cout << p2.age << endl;
}
int main() {
	zhixing();
	return 0;
}

四.空指针访问成员函数

C++中空指针也是可以调用成员函数的,但是也要注意有没有用到this指针

代码: 

#include <iostream>
using namespace std;
class person {
public:
	int age;
	void fun1() {
		cout << "fun1调用" << endl;
	}
	void fun2() {
		cout << "fun2调用" << age << endl;
	}

};
void diaoyong() {
	person* p = NULL;
	p->fun1();
	p->age = 10;
	p->fun2();
}
int main() {
	diaoyong();
	return 0;
}

 只能成功调用没有this指针的函数,因为此时this是空指针,含有this的调用

 代码:

#include <iostream>
using namespace std;
class person {
public:
	int age;
	void fun1() {
		cout << "fun1调用" << endl;
	}
	void fun2() {
		if (this == NULL) {
			return;
		}
		cout << "fun2调用" << age << endl;
	}

};
void diaoyong() {
	person* p = NULL;
	p->fun1();
	p->fun2();
}
int main() {
	diaoyong();
	return 0;
}

增加代码的健壮性,判断this指针是空指针的时候,跳出函数。

 五.const修饰成员函数

 常函数:

1.成员函数后加const后我们称为这个函数为常函数。

2.常函数内不可以修改成员属性。

3.成员属性声明时加关键字mutable后,在常函数中依然可以修改。

常对象:

1.声明对象前加const称对象为常对象。

2.常对象只能调用常函数和用mutable修饰的成员变量。

 5.1常函数

this指针本质是指针常量,指针的指向是不可以修改的(person* const this),但是this指针指向地址的值是可以发生改变的。

 常函数const要加在函数参数列表后面

代码: 

#include <iostream>
using namespace std;
class person {
public:
	int age;
	void showage(int m) const{
	//	age = 89; //报错
		m = 100;
		cout << "age=" << age <<" m=" << m << endl;
	}
};
void fun() {
	person p;
	p.age = 10;
	p.showage(7);
}
int main() {
	fun();
	return 0;
}

 此时编译器会报错,此时age在函数内是不可改变的。但是函数传的参数,仍然是可以改变的。

#include <iostream>
using namespace std;
class person {
public:
	mutable int age;
	void showage(int m) const{   //常函数
		age = 89; //报错
		m = 100;
		cout << "age=" << age <<" m=" << m << endl;
	}
};
void fun() {
	person p;
	p.age = 10;
	p.showage(7);
}
int main() {
	fun();
	return 0;
}

成员属性声明时加关键字mutable后,在常函数中依然可以修改。

5.2 常对象

 代码:

#include <iostream>
using namespace std;
class person {
public:
	mutable int age;
	void showage1(int m) const{
		//age = 89; //报错
		m = 100;
		cout << "age=" << age <<" m=" << m << endl;
	}
	void showage2(int m)  {
		age = 89;
		m = 100;
		cout << "age=" << age << " m=" << m << endl;
	}
};
void fun() {
	const person p;
	p.age = 10;      
	p.showage1(7);
	//p.showage2(7);  报错  
}
int main() {
	fun();
	return 0;
}

常对象只能调用常函数和用mutable修饰的成员变量。普通函数和普通成员变量不能调用

 六.友元

友元关键字:friend

友元的三种实现:

1.全局函数做友元

2.类做友元

3.成员函数做友元

6.1全局函数做友元 

 代码:

#include <iostream>
using namespace std;

class home {
friend void func(home& p);
public:
	home(string keting, string woshi, string cuosuo):keting(keting),woshi(woshi),cuosuo(cuosuo) {

	}
	string keting;
private:
	string woshi;
protected:
	string cuosuo;
};

void func(home &p) {
	
	cout << p.keting << ' ' << p.woshi << ' ' << p.cuosuo << endl;
}
void fun() {
	home p("客厅", "卧室", "厕所");
	func(p);
}
int main() {
	fun();
	//cout << p.keting << ' ' << p.woshi << ' ' << p.cuosuo << endl;
	//保护和私有属性的不能访问
	return 0;
}

有元函数不是类的成员函数,但是却又权限调用类的所有成员变量

6.2类做友元 

​​#include <iostream>
using namespace std;

class building {
friend class goodgay;   //声明友元类
public:
	building();
	string keting;
private:
	string cesuo;
protected:
	string woshi;
};
building::building() {
	keting = "客厅";
	cesuo = "厕所";
	woshi = "卧室";
}

class goodgay {
public:
	goodgay();
	void show();
private:
	building* p;
};
void goodgay::show() {
	cout << this->p->keting << ' ' << this->p->cesuo << ' ' << this->p->woshi << endl;
}
goodgay::goodgay() {
	p = new building;
}
void f() {
	goodgay a;
	a.show();
}
int main() {
	f();
	return 0;
}

 类做友元,类中的所有成员函数都能访问友元类中所有成员。

 6.3成员函数做友元

 代码:

#include <iostream>
using namespace std;
class building;
class goodgay {
public:
	goodgay();
	void show1(building& p);
private:
	building* p;
};

class building {
friend void goodgay::show1(building& p);   //声明友元类
public:
	building();
	string keting;
private:
	string cesuo;
protected:
	string woshi;
};
building::building() {
	keting = "客厅";
	cesuo = "厕所";
	woshi = "卧室";
}


void goodgay::show1(building& p1) {
	cout <<p1.keting << ' ' << p1.cesuo << ' ' << p1.woshi << endl;
}
//void goodgay::show2() {
//	cout << this->p->ketipng << ' ' << this->p->cesuo << ' ' << this->p->woshi << endl;
//}
//无权限
goodgay::goodgay() {
	p = new building;
}
void f() {
	goodgay a;
	building b;
	a.show1(b);
}
int main() {
	f();
	return 0;
}

注意类要先声明一下,防止报错,与全局函数做友元不同的是,要加上作用域。

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

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

相关文章

Obsidian配置

插件 1&#xff1a;Annotator pdf批注插件&#xff0c;使用方法&#xff1a;新建一个markdown文件&#xff0c;在文件的头部必须时开头添加以下内容&#xff1a; --- annotation-target: xxx.pdf ---2&#xff1a;Hidden Folder 用正则表达式隐藏文件夹的&#xff0c;我的设…

Spring实例化源码解析(一)

invokeBeanFactoryPostProcessors 前言 AbstractApplicationContext类的refresh方法是spring实例化流程的开始。本章主要是介绍invokeBeanFactoryPostProcessors(beanFactory)方法&#xff0c;对其内部源码进行详细分析。接下来就来看看这句简单的代码后面具体做了什么。Spri…

SpringSecurity学习 - 认证和授权

一般来说中大型的项目都是使用SpringSecurity 来做安全框架。小项目有Shiro的比较多&#xff0c;因为相比与SpringSecurity&#xff0c;Shiro的上手更加的简单。 一般Web应用的需要进行认证和授权。 认证&#xff1a;验证当前访问系统的是不是本系统的用户&#xff0c;并且要…

C语言实现通讯录 (附完整代码)

C语言实现通讯录 &#x1f340;实现一个通讯录&#xff1a;&#x1f340;通讯录的功能&#xff1a;&#x1f340;多文件实现&#x1f4ae;设计结构体——保存人的信息&#x1f4ae;初始通讯录&#x1f4ae;封装通讯录&#x1f4ae;define宏定义修改通讯录的最大容量初始化通讯录…

【机器学习】文本多分类

声明&#xff1a;这只是浅显的一个小试验&#xff0c;且借助了AI。使用的是jupyter notebook,所以代码是一块一块&#xff0c;从上往下执行的 知识点&#xff1a;正则删除除数字和字母外的所有字符、高频词云、混淆矩阵 参考&#xff1a;使用python和sklearn的中文文本多分类…

JDK9特性——语法、API的改变

文章目录 语法层次改变钻石操作符号语法升级try结构语法升级下划线命名标识符的使用限制 API层次的改变接口中的私有方法String底层存储结构变化Stream新增4个APIInputStream新增transferTo方法只读集合创建 语法层次改变 钻石操作符号语法升级 钻石操作符&#xff0c;就是我…

LeetCode(力扣)738. 单调递增的数字Python

LeetCode738. 单调递增的数字 题目链接代码 题目链接 https://leetcode.cn/problems/monotone-increasing-digits/description/ 代码 class Solution:def monotoneIncreasingDigits(self, n: int) -> int:strNum str(n)flag len(strNum)for i in range(len(strNum) - …

ffmpeg6.0编译(NDK)

ffmpeg 6.0 支持vulkan 需要手动安装Vulkan 并将include里面的vk_video 和 vulkan 拷贝到 android-ndk-r25c/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/ vulkan 下载 cp -r vk_video $NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/…

前端vue3分享——项目封装axios、vite使用env环境变量

文章目录 ⭐前言⭐vue3封装统一的axios请求&#x1f496; 请求拦截器 ⭐vue3使用env环境变量&#x1f496; vite env变量规则&#x1f496; vite.config获取env参数 ⭐总结&#x1f496; 编码sliod原则 ⭐结束 ⭐前言 大家好&#xff0c;我是yma16&#xff0c;本文分享关于前端…

iOS开发之编译OpenSSL静态库

项目审查发现OpenSSL1.0.2d有漏洞&#xff0c;所以需要升级更新OpenSSL版本&#xff0c;借此机会&#xff0c;记录一下编译OpenSSL静态库的流程。 Xcode使用的是14.2&#xff0c;OpenSSL使用的是1.0.2u、1.1.1u&#xff0c;由于是对两个不同版本进行的编译操作&#xff0c;所以…

企业架构LNMP学习笔记55

MongoDB的安装和配置&#xff1a; 1、安装方式介绍&#xff1a; yum安装方式&#xff1a; 手动通用安装方式&#xff1a; 2、二进制可执行安装&#xff1a; 下载路径&#xff1a;Download MongoDB Community Server | MongoDB 下载mongodb的源码包进行安装。 1&#xff09;…

220kV 及以下避雷器直流泄露电流试验

试验步骤: 1) 记录试验现场的环境温度、 湿度。 2) 对被试设备充分放电后可靠接地。 3) 试验前正确设置安全围栏和悬挂标示牌。 4) 做上节避雷器直流试验时, 根据图进行试验接线, 微安表的一端夹子接在上节避雷器的下端, 另一端安装在高压直流发生器的电压输出端, 上节避雷…

cgroup限制内存

首先简单介绍下cgroup限制cpu的使用率&#xff0c;写一段代码如下&#xff1a; #include <stdio.h> #include <pthread.h>int main() { int i 0; for(;;)i; return 0; }很明显&#xff0c;这里面是单核拉满&#xff0c;然后top看下进程的cpu使用率&#xff0c;如…

【深度学习】Pytorch 系列教程(十四):PyTorch数据结构:6、模块(Module):前向传播

目录 一、前言 二、实验环境 三、PyTorch数据结构 0、分类 1、张量&#xff08;Tensor&#xff09; 2、张量操作&#xff08;Tensor Operations&#xff09; 3、变量&#xff08;Variable&#xff09; 4、数据集&#xff08;Dataset&#xff09; 5、数据加载器&#x…

科学计算器网站Desmos网站

科学计算器网站Desmos网站 有时在学习工作或者生活中&#xff0c;需要用到计算问题&#xff0c;但由于电脑上没有安装相应的专业软件&#xff0c;难以计算有的问题&#xff0c;因而&#xff0c;本文推荐一种免费的在线计算网站Desmos。 一、Desmos网址 Desmos官网的地址为&a…

[管理与领导-96]:IT基层管理者 - 扩展技能 - 5 - 职场丛林法则 -10- 七分做,三分讲,完整汇报工作的艺术

目录 前言&#xff1a; 一、汇报工作的重要性 1.1 汇报的重要性&#xff1a;汇报工作是工作重要的一环 1.2 向上司汇报工作状态具有重要的意义 1.2 汇报工作存在一些误解 1.3 汇报工作中的下错误做法 1.4 汇报工作与做实际工作的关系 二、工作汇报的内容与艺术 2.1 工…

【深度学习】- NLP系列文章之 1.文本表示以及mlp来处理分类问题

系列文章目录 1. 文本分类与词嵌入表示&#xff0c;mlp来处理分类问题 2. RNN、LSTM、GRU三种方式处理文本分类问题 3. 评论情绪分类 还是得开个坑&#xff0c;最近搞论文&#xff0c;使用lstm做的ssd的cache prefetching&#xff0c;意味着我不能再划水了。 文章目录 系列文章…

js创建动态key的对象ES6和ES5的方法

前提&#xff1a; 有个场景&#xff0c;循环数组&#xff0c;根据每一项的值&#xff0c;往一个数组中push一个新对象&#xff0c;对象的key不同要从数组中获取 情况解析&#xff1a;push没有什么问题&#xff0c;问题就是创建一个动态key的对象。下面就说一下如何以参数为key…

【pwn入门】基础知识

声明 本文是B站你想有多PWN和星盟安全学习的笔记&#xff0c;包含一些视频外的扩展知识。 工具和命令 常见的工具 pwntools安装checksec安装pwndbg的安装和gdb使用ubuntu没有使用全部磁盘空间 sudo lvextend -l 100%FREE /dev/mapper/ubuntu--vg-ubuntu--lv sudo resize2f…

Vue中一键批量注册全局组件

文件目录如下 1. component文件夹中编写所有的公共组件 注意&#xff1a;之后一键注册的全局组件名就是每个公共组件&#xff08;xxx.vue&#xff09;文件的文件名 xxx 2. plugins/components.js中批量注册组件 import Vue from "vue"let requireFile require.con…