类的成员函数与内联以及静态成员

一、类的成员函数与内联

在类内定义的所有函数都自动称为内联函数。如果在类内声明,在类外定义,也可以定义为内联函数。在定义函数时添加inline限定符。。
(1)此外,内联函数一定要和函数定义在一起,否则只是声明的时候加上内联,是不会成为内联函数的
声明:inline void fun();
函数体:void fun(){}
这样只有声明带内联,函数定义时没有带内敛,所以fun不是内联函数。
(2)inline一定要和函数定义在一起。
声明:void fun();
定义:inline void fun(){}
这样可以,但是后来我才知道这样还会存在一点问题。比如下面。
(3)
声明:void fun();
调用:fun();
定义:inline fun(){}
声明没有inline,定义有inline,但是调用在定义前,这样也不会成为内联。(这一点是我在一篇2015年博客上看到后才知道的,但是现在这样到底会不会成为内联函数,我也不确定)
但是最保险的做法是,定义和声明都加上inline关键字。
除了这些之外,编译器会自动取消掉不合适的内联。

二、普通成员函数的this指针

类的成员变量和成员函数是分开存储的,只有非静态成员变量才属于实例化出来的对象,每个对象都有一份。非静态成员函数只有一份。
类的每一个非静态成员函数都有一个this指针。而且是指针常量。即T* const this类型。T为类型。所以可以看出不能更改this指针的指向。而且是这个形参是隐式包含在形参列表中的。this指针指向调用这个成员函数的对象本身。
用途:
(1)区分与成员变量相同名称的形参。
即如果成员函数的形参与成员变量名相同,那么可以用this->“成员变量名”,以这种形式区分成员变量和形参。
(2)返回对象本身。
this是指向对象本身的,那么在成员函数体内,*this就是指对象本身。

三、空指针访问成员函数

在C++中空指针是可以调用成员函数的。如果用到this指针了,那么就会报错,如果没有用到this指针,就不会报错。这个时候就要考虑代码的健壮性了。比如下面举例:
代码1:

class Student
{
public:
	Student() 
	{
		cout << "this is Student()" << endl;
	}
	~Student()
	{
		cout << "this is ~Student()" << endl;
	}

	void fun1() 
	{
		cout << "this is fun()" << endl;
	}
	void fun2()
	{
		this->id = 10;
	}
private:
	int id;
	string name;
};

void test()
{
	Student* p = nullptr;
	p->fun1();
}

int main()
{
	test();
	return 0;
}

运行结果:
在这里插入图片描述
代码2:

class Student
{
public:
	Student() 
	{
		cout << "this is Student()" << endl;
	}
	~Student()
	{
		cout << "this is ~Student()" << endl;
	}

	void fun1() 
	{
		cout << "this is fun1()" << endl;
	}
	void fun2()
	{
		this->id = 10;
		cout << "this is fun2()" << endl;
	}
private:
	int id;
	string name;
};

void test()
{
	Student* p = nullptr;
	p->fun2();
}

int main()
{
	test();
	return 0;
}

运行结果:

在这里插入图片描述
用的编译器是vs2019,出乎意料的是居然没有崩溃,但是程序返回值是一个很多位的随机值,说明返回的是错误码,之前都是直接弹出来窗口说崩溃。按道理来说是理应崩溃的。因为我们在fun2()里面用了this->这个语句。->有解引用步骤,对空指针解引用,肯定不行,所以理应崩溃,可能是VS2019编译器优化了返回错误码,没有弹窗告诉崩溃。运行没崩溃,但是我调试了一下,报错了。
在这里插入图片描述
所以一般情况下,为了防止这种情况发生,最好在成员函数里,对this指针加一个非空判断。

四、const修饰的成员函数和成员变量

1.基本概念

(1)成员函数后加上const后,我们称之为常函数,常函数不能修改成员属性。
(2)成员变量加上const后,称之为常变量。不能修改值。常成员变量一定要初始化。
(3)定义对象前加const,即为长对象,由于常对象的属性不允许修改,所以常对象只能调用常函数。比如const Student stu;stu就是常对象。一下举例常对象和常成员函数
代码:

class Student
{
public:
	Student(int i, string na) :id(i), name(na)
	{
		cout << "this is Student()" << endl;
	}
	~Student()
	{
		cout << "this is ~Student()" << endl;
	}
	int GetId()const
	{
		cout << "this is GetId()const" << endl;
		return id;
	}
	int GetId()
	{
		cout << "this is GetId()" << endl;
		return id;	return id;
	}
private:
	int id;
	string name;
};


int main()
{
	const Student stu1(100,"xiaomeng");
	stu1.GetId();
	Student stu2(200, "xiaohua");
	stu2.GetId();

	return 0;
}

运行结果:
在这里插入图片描述
注意,我们对GetId函数重载了。stu1是常对象,在这里只能调用常成员函数GetId()const。stu2是普通对象,可以调用GetId(),也可以调用GetId()const,而且还都是完全匹配。只不过GetId()更有优先性。这里对象调用重载的成员函数规则,和我们函数重载规则一样。
其中如果我们想要在常成员函数里修改某一个成员变量,而其他成员变量仍要求不能修改的话,我们可以用mutable关键字,如下:

class Student
{
public:
	Student(int i, string na) :id(i), name(na)
	{
		cout << "this is Student()" << endl;
	}
	~Student()
	{
		cout << "this is ~Student()" << endl;
	}
	int GetId()const
	{
		name = "xiaomeng";
		//id = 200;//error
		cout << "this is GetId()const" << endl;
		return id;
	}
	void Show()
	{
		cout << "name: " << name << "   " << "id: " << id << endl;
	}
private:
	int id;
	mutable string name;
};


int main()
{
	Student stu(100, "xiaohua");
	stu.GetId();
	stu.Show();

	return 0;
}

注意,成员变量name加了关键字mutable,GetId()const函数里,对name修改了。
运行结果:
在这里插入图片描述
发现name从“xiaohua”修改成了“xiaomeng”。

五、静态成员变量

(1)所有对象共用一个静态成员变量。
(2)类内声明,必须在类外初始化,在类内不允许给初始值。(const static类型必须在类内给初始值)
(3)在编译阶段就给静态变量分配内存,存储在静态变量区。受访问权限限制。
(4)静态成员变量只有被初始化后才能调用,否则调用静态变量编译出错。
(5)当静态成员变量访问权限为公有时,可以用对象名访问,可以用成员函数访问,可以用类名访问。当静态成员变量为私有成员权限时,只可以以调用成员函数的方式(包括普通成员函数和静态成员函数)访问。

class Student
{
public:
	Student(int i, string na) :id(i), name(na) {}
	~Student() {}
	static  void fun1()
	{
		//可以访问静态成员变量
		cout << "this is static fun1()" << "s_1 = " << s_t1 << "   " << "s_t2 = " << s_t2 << endl;
	}
	void Show()
	{
		cout << &(this->s_t1) << endl;
	}
	
private:
	const static int s_t1 = 10;//静态常量成员可以直接在类内初始化
	static int s_t2;//非常量静态成员变量必须在类外初始化。
	int id;
	string name;
};

int Student::s_t2 = 50;

int main()
{
	Student stu1(100, "xiaohua");
	stu1.fun1();
	stu1.Show();

	Student stu2(200, "xiaomeng");
	stu2.fun1();
	stu2.Show();

	return 0;
}

运行结果:

在这里插入图片描述

六、静态成员函数

(1)静态成员函数没有this指针
(2)所有对象共享一个静态成员函数。
(3)静态成员函数只能访问静态成员变量(没有this指针)。
(4)静态成员函数类内类外都可以定义。
(5)静态成员函数受访问权限的限制
访问静态成员变量的方式:
(1)通过对象访问
(2)通过域名访问
如下举例静态成员函数的声明,在类内定义,类外定义,和调用方式:

class Student
{
public:
	Student(int i, string na) :id(i), name(na)
	{
		cout << "this is Student()" << endl;
	}
	~Student()
	{
		cout << "this is ~Student()" << endl;
	}
	static void fun1()
	{
		//id = 200;//error,静态成员函数没有this指针,没办法访问成员变量.如果写成这种static void fun(Student stu),可以访问形参的成员变量
		cout << "this is static void fun1()" << endl;
	}
	static void fun2();
	void Show()
	{
		cout << "name: " << name << "   " << "id: " << id << endl;
	}
private:
    static  void fun3()
	{
		cout << "this is static fun3()" << endl;
	}
	int id;
	string name;
};

void  Student::fun2()//类外定义静态成员函数
{
	cout << "this is static fun2()" << endl;
}

int main()
{
	Student stu(100, "xiaohua");
	stu.fun1();//通过对象访问静态成员函数
	Student::fun1();//通过域名访问静态成员函数

	return 0;
}

注意fun3是私有权限,不可以在类外用对象或者类名访问。

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孟小胖_H

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值