浅谈C++|类的成员

一.类对象作为类成员

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

代码:

cpp 复制代码
#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静态成员变量

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

。在编译阶段分配内存。

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

代码:

cpp 复制代码
#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;
}

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

代码:

cpp 复制代码
#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静态成员函数

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

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

代码:

cpp 复制代码
#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++编译器会给每个空对象也分配一个字节空间,是为了区分对象占内存的位置

代码:

cpp 复制代码
#include <iostream>
using namespace std;
class person {

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

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

代码:

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

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

代码:

cpp 复制代码
#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

代码:

cpp 复制代码
#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;
}

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

cpp 复制代码
#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指针

代码:

cpp 复制代码
#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的调用

代码:

cpp 复制代码
#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要加在函数参数列表后面

代码:

cpp 复制代码
#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在函数内是不可改变的。但是函数传的参数,仍然是可以改变的。

cpp 复制代码
#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 常对象

代码:

cpp 复制代码
#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全局函数做友元

代码:

cpp 复制代码
#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类做友元

cpp 复制代码
​​#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成员函数做友元

代码:

cpp 复制代码
#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;
}

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

相关推荐
源码哥_博纳软云1 分钟前
JAVA同城服务场馆门店预约系统支持H5小程序APP源码
java·开发语言·微信小程序·小程序·微信公众平台
学会沉淀。9 分钟前
Docker学习
java·开发语言·学习
ragnwang26 分钟前
C++ Eigen常见的高级用法 [学习笔记]
c++·笔记·学习
西猫雷婶39 分钟前
python学opencv|读取图像(二十一)使用cv2.circle()绘制圆形进阶
开发语言·python·opencv
kiiila40 分钟前
【Qt】对象树(生命周期管理)和字符集(cout打印乱码问题)
开发语言·qt
小_太_阳1 小时前
Scala_【2】变量和数据类型
开发语言·后端·scala·intellij-idea
直裾1 小时前
scala借阅图书保存记录(三)
开发语言·后端·scala
唐 城1 小时前
curl 放弃对 Hyper Rust HTTP 后端的支持
开发语言·http·rust
火星机器人life2 小时前
基于ceres优化的3d激光雷达开源算法
算法·3d
虽千万人 吾往矣2 小时前
golang LeetCode 热题 100(动态规划)-更新中
算法·leetcode·动态规划