C++学习笔记(十三)

在完成对C语言的学习后,我最近开始了对C++和Java的学习,目前跟着视频学习了一些语法,也跟着敲了一些代码,有了一定的掌握程度。现在将跟着视频做的笔记进行整理。本篇博客是整理C++知识点的第十三篇博客。

本篇博客介绍了C++的类的成员特性和友元。

本系列博客所有C++代码都在Visual Studio 2022环境下编译运行。程序为64位。

目录

成员特性

静态成员

类的成员的存储

this指针

空指针访问成员函数

const修饰成员函数

友元

全局函数做友元

友元类

成员函数作为友元


成员特性

静态成员

在成员变量和成员函数前加关键字static,就成为静态成员。

静态成员变量是所有对象共享同一份数据,在编译阶段分配内存,类内声明,类外初始化。

静态成员函数是所有对象共享同一个函数,只能访问静态成员变量。

静态成员变量和静态成员函数可以通过对象和类名进行访问,但是依然有权限,私有的不可在类外访问。

#include<iostream>
using namespace std;
class test {
public:
	static int num;
	static void show() {
		cout << "This is a test" << endl;
		cout << "num = " << num << endl;
	}
private:
	static int number;
	static void func() {
		cout << "This is a function" << endl;
	}
};
int test::num = 10;
int main(void)
{
	test::show();

	test testtemp;
	testtemp.num = 20;
	testtemp.show();
	return 0;
}

类test有public权限的,静态的int类型成员变量num,和show函数,show函数访问num。也有private权限的静态的成员变量number和成员函数func。在类外初始化num的值为10,此处加作用域表明属于test类。

main函数首先直接用类名访问了test类的show函数,随后实例化了一个对象,再通过对象修改num值为20并访问show函数。

程序的输出是:

This is a test
num = 10
This is a test
num = 20
 

类的成员的存储

在C++中,只有非静态的成员变量才属于类的对象,其余都不属于。如果一个类对象没有非静态成员变量,那么会被分配一字节空间。

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

};
class test2 {
	int num;
	static int number;
	void show1(){}
	static void show2(){}
};
int main(void)
{
	cout << sizeof(test1) << endl;
	cout << sizeof(test2) << endl;
	return 0;
}

程序创建了两个类,test1类完全为空,test2类有非静态int变量,静态的int变量,静态函数,非静态函数各一个。程序获得这两个类的大小。程序输出:

1
4
 

this指针

this指针指向被调用的成员函数所属对象。this指针隐含在每个非静态成员函数内,不需要定义,可以直接使用。

this指针可以用来区别同名形参和成员变量。另外,在类的非静态成员变量函数中返回对象本身可以用return *this。

#include<iostream>
using namespace std;
class test {
private:
	int num;
public:
	int getnum() {
		return num;
	}
	void setnum(int num) {
		this->num = num;
	}
};
int main(void)
{
	test temp;
	temp.setnum(10);
	cout << temp.getnum() << endl;
	return 0;
}

程序的test类创建了private权限的变量num,以及对应的get和set函数。在setnum函数中使用this指针区分同名形参和成员变量。程序的输出是:

10

#include<iostream>
using namespace std;
class test{
public:
	int age;
	test& addage(test &temp) {
		this->age += 1;
		return *this;
	}
};
int main(void)
{
	test temp;
	test fixed;
	fixed.age = 1;
	temp.age = 95;
	temp.addage(fixed);
	temp.addage(fixed);
	temp.addage(fixed);
	temp.addage(fixed);
	temp.addage(fixed);
	cout << "The age is " << temp.age << endl;
	return 0;
}

程序创建了一个test类,有一个成员变量age,和一个成员函数addage。addage成员函数接受一个test类对象的引用,将本类的成员age+1,随后返回本类对象。

程序的输出是:

The age is 100
 

空指针访问成员函数

空指针也可以调用成员函数,但是要注意有没有用到this指针。如果空指针调用时遇到this指针,程序崩溃。

#include<iostream>
using namespace std;
class test {
public:
	int age;
	void show1(void) {
		cout << "This is null" << endl;
	}

	void show2(void) {
		if (this == NULL) {
			return;
		}
		cout << "The age is " << age << endl;
	}
};

int main(void)
{
	test* p = NULL;
	(*p).show1();
	(*p).show2();
	return 0;
}

test类有成员变量age,成员函数show1和show2。show1函数输出This is null。show2函数进行判断,如果是空指针就结束,否则输出age的值。

main函数中创建了一个test类指针,并赋值为NULL。随后调用show1和show2函数。程序的输出是:

This is null

const修饰成员函数

在成员函数后加const就称为常函数,常函数内不可以修改成员属性。然而,在成员属性声明时加关键字mutable后,就可以在常函数中修改。

在声明对象前加const就称为常对象,常对象只能调用常函数。

#include<iostream>
using namespace std;
class test {
public:
	int number = 10;
	mutable int num = 10;
	void show(void) const {
		num = 15;
		cout << number << endl;
		cout << num << endl;
	}
};
int main(void)
{
	test temp;
	temp.show();
	return 0;
}

test类的变量num被mutable修饰,成员函数show是常函数,内部修改了num的值,并进行一些输出。main函数创建了一个test类对象并调用show成员函数。

程序的输出是:

10
15

#include<iostream>
using namespace std;
class test {
public:
	int number = 10;
	mutable int num = 10;
	void show1(void) const {
		cout << number << endl;
		cout << num << endl;
	}
	void show2(void) {
		number = 20;
		num = 25;
		cout << number << endl;
		cout << num << endl;
	}
};
int main(void)
{
	const test temp;
	temp.num = 5;
	temp.show1();
	return 0;
}

test类的成员变量num被mutable修饰。成员函数show1是常函数,show2不是常函数。

main函数创建了一个test类的常对象,调用了show1函数。

程序的输出是:

10
5

友元

有时候,需要访问某个类的private权限成员,就需要用友元。友元的目的是让一个函数或类访问另一个类的private成员。友元的关键字是friend

友元可以通过全局函数,类或成员函数实现。

全局函数做友元

全局函数作为友元,需要在类的最上面加入要作为友元的函数的声明,同时前面加friend。

#include<iostream>
using namespace std;
class test {
	friend void look(test* p);
public:
	int number = 10;
private:
	int num = 15;
};

void look(test* p);
int main(void)
{
	test temp;
	look(&temp);
	return 0;
}

void look(test* p)
{
	cout << (*p).number << endl;
	cout << (*p).num << endl;
}

test类有一个public权限的变量number,一个private权限的变量num。同时第一行声明look函数是友元。look函数接受一个test类指针作为参数,随后访问number和num成员。main函数创建了一个test类对象,随后将其作为参数传递给look函数。

程序的输出是:

10

15

友元类

需要在类的第一行用friend class 类名;声明后面的类是友元类。

#include<iostream>
using namespace std;
class test {
	friend class look;
public:
	int number = 10;
private:
	int num = 15;
};

class look {
public:
	test *temp = new test();
	void show(void);

	~look() {
		delete temp;
	}
};

void look::show(void)
{
	cout << (*temp).number << endl;
	cout << (*temp).num << endl;
}

int main(void)
{
	look tmp;
	tmp.show();
	return 0;
}

test类有public权限的变量number和private权限的变量num。同时声明look为友元类。look类有一个成员变量temp,是test类的指针,开辟在堆区。成员函数show函数(实现在类外)访问temp的两个成员变量。main函数创建了一个look类对象,并调用show函数。

程序的输出是:

10
15

成员函数作为友元

要在类的第一行放上成员函数的声明(加上作用域表明属于哪个类),然后前面加friend。

#include<iostream>
using namespace std;
class test;

class look {
public:
	test* temp;
	look();
	void show1(void);
	void show2(void);
	~look() {
		delete temp;
	}
};
class test {
	friend void look::show1(void);
public:
	int number = 10;
private:
	int num = 15;
};

look::look() {
	temp = new test;
}
void look::show1(void)
{
	cout << (*temp).number << endl;
	cout << (*temp).num << endl;
}
void look::show2(void)
{
	cout << (*temp).number << endl;
}
int main(void)
{
	look tmp;
	tmp.show1();
	tmp.show2();
	return 0;
}

第三行的class test;表明程序有一个test类,但是其定义在别处。下面的look类有一个test类指针temp作为成员,析构函数将temp释放。其构造函数,show1函数和show2函数的实现在下面。下面test类有public类型成员变量number和private类型成员变量num。test类第一行表明look类的show1函数是友元。再下面具体实现look类的构造函数,以及show1和show2函数。

main函数创建了一个look类对象,并调用show1和show2函数。

程序的输出是:

10
15
10
 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值