在完成对C语言的学习后,我最近开始了对C++和Java的学习,目前跟着视频学习了一些语法,也跟着敲了一些代码,有了一定的掌握程度。现在将跟着视频做的笔记进行整理。本篇博客是整理C++知识点的第十三篇博客。
本篇博客介绍了C++的类的成员特性和友元。
本系列博客所有C++代码都在Visual Studio 2022环境下编译运行。程序为64位。
目录
成员特性
静态成员
类的成员的存储
this指针
空指针访问成员函数
const修饰成员函数
友元
全局函数做友元
友元类
成员函数作为友元
在成员变量和成员函数前加关键字static,就成为静态成员。
静态成员变量是所有对象共享同一份数据,在编译阶段分配内存,类内声明,类外初始化。
静态成员函数是所有对象共享同一个函数,只能访问静态成员变量。
静态成员变量和静态成员函数可以通过对象和类名进行访问,但是依然有权限,私有的不可在类外访问。
#include
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
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指针可以用来区别同名形参和成员变量。另外,在类的非静态成员变量函数中返回对象本身可以用return *this。
#include
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
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
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就称为常函数,常函数内不可以修改成员属性。然而,在成员属性声明时加关键字mutable后,就可以在常函数中修改。
在声明对象前加const就称为常对象,常对象只能调用常函数。
#include
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
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
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
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
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