【C++】类和对象(二)

耐心、韧性、谅解、宽容、包涵,都是爱的代名词。

前言

这是我自己学习C++的第三篇博客总结。后期我会继续把C++学习笔记开源至博客上。 上一期笔记是关于C++的类和对象,没看的同学可以过去看看: 【C++】类和对象(一)-CSDN博客

初始化列表

1. 在调用构造函数时,成员变量的初始化通常有两种方式:一种是在构造函数体内进行赋值,另一种是通过初始化列表进行赋值。 2. 初始化列表的使用方法如下:以冒号开头,随后是一个由逗号分隔的成员变量列表,每个成员变量后面紧跟一对圆括号,括号中包含该变量的初始值或初始化表达式。 3. 引用类型的成员变量const修饰的成员变量自定义类型的成员变量必须放在初始化列表进行初始化,否则会编译报错。 4. C++11支持在成员变量声明时给缺省值,这个缺省值主要是给没有显示的在初始化列表初始化的成员使用的。 5. 尽量使用初始化列表,因为那些你不在初始化列表初始化的成员也会走初始化列表。 6. 初始化列表按照成员变量在类中声明先后顺序进行初始化,与成员在初始化列表出现的先后顺序无关。故建议声明顺序和初始化列表顺序保持一致

代码语言:javascript代码运行次数:0运行复制
#include<iostream>
using namespace std;

class Time
{
public:
	Time(int hour)
		:_hour(hour)
	{
		cout << "Time()" << endl;
	}
private:
	int _hour;
};

class Date
{
public:
	Date(const int& x, int year = 1, int month = 1, int day = 1)
		:_year(year)
		, _month(month)
		, _day(day)
		, _t(12)
		, _ref(x)
		, _n(1)
	{}
	void Print() const 
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _year = 10;//可以在声明时候给缺省值
	int _month = 10;
	int _day = 10;
	Time _t; 
	int& _ref; 
	const int _n; 
};

int main()
{
	int i = 0;
	Date d1(i);
	d1.Print();//1 1 1
	return 0;
}

友元

1. 友元提供了一种突破封装的方式,友元分为:友元函数友元类。 2. 友元声明时,需要在友元函数或者友元类前面加friend,并且把友元声明放到对应的类的里面。 3. 友元函数可以访问类的私有和保护成员,但不是这个类的成员函数。 4. 友元函数可以在类定义的任何地方声明,不受类访问限定符限制。 5. 一个函数可以是多个类的友元函数。 6. 友元类中所有的成员函数都是另一个类的友元函数,都可以访问另一个类的私有成员和保护成员。 7. 友元关系是单向的不能传递的

代码语言:javascript代码运行次数:0运行复制
//友元函数
#include <iostream>
using namespace std;

class B;//先声明一个B类类型,否则A中声明友元函数时,找不到B的类型。

class A 
{
	friend void func(const A& aa, const B& bb);// 友元声明
private:
	int _a1 = 1;
	int _a2 = 2;
};

class B
{
	friend void func(const A& aa, const B& bb);// 友元声明
private:
	int _b1 = 3;
	int _b2 = 4;
};

void func(const A& aa, const B& bb)
{
	cout << aa._a1 << endl;
	cout << bb._b1 << endl;
}

int main()
{
	A aa;
	B bb;
	func(aa, bb);
	return 0;
}
//1
//3
代码语言:javascript代码运行次数:0运行复制
//友元类
#include<iostream>
using namespace std;
class A
{
	friend class B;	// 友元声明
private:
	int _a1 = 1;
	int _a2 = 2;
}; 

class B
{
public:
	void func1(const A& aa)
	{
		cout << aa._a1 << endl;
		cout << _b1 << endl;
	}
	void func2(const A& aa)
	{
		cout << aa._a2 << endl;
		cout << _b2 << endl;
	}
private:
	int _b1 = 3;
	int _b2 = 4;
};
int main()
{
	A aa;
	B bb;
	bb.func1(aa);
	bb.func1(aa);
	return 0;
}
//1
//3
//1
//3

内部类

1. 如果一个类定义在另一个类的内部,那么前面这个类就叫做内部类。 2. 内部类是一个独立的类,只是受外部类的类域限制和访问限定符限制。这意味着内部类虽然位于外部类的命名空间内,但并不依赖于外部类的实例,即外部类定义的对象中不包含内部类。 3. 内部类默认是外部类的友元类内部类可以访问外部类的成员。 3. 内部类本质也是一种封装,当A类跟B类紧密关联,A类的主要功能是为了服务于B类,那么可以考虑把A类设计为B类的内部类,如果将A类放置在B类的privateprotected位置,那么A类就是B类的专属内部类,其他地方都用不了。

代码语言:javascript代码运行次数:0运行复制
#include<iostream>
using namespace std;

class A
{
private:
	static int _k;
	int _h = 1;
public:
	class B // B默认就是A的友元
	{
	public:
		void foo(const A& a)
		{
			cout << _k << endl; //OK
			cout << a._h << endl; //OK
		}
	};
};
int A::_k = 1;
int main()
{
	cout << sizeof(A) << endl;//4
	A::B b;
	A aa;
	b.foo(aa);//1 1
	return 0;
}

static修饰

1. 使用static修饰的成员变量,称为静态成员变量,静态成员变量必须要在类外初始化。 2. 静态成员变量为类的所有对象所共享,不属于某个具体的对象,存放在静态区。 3. 使用static修饰的成员函数,称为静态成员函数,静态成员函数没有this指针。 4. 可以在静态成员函数中访问静态成员变量,但是不能访问非静态的成员变量,因为静态成员函数没有this指针。 5. 可以在非静态的成员函数中访问任意的静态成员变量静态成员函数。 6. 突破类域就可以访问静态成员,可以通过 类名::静态成员 或者 对象.静态成员 的方式来访问静态成员变量和静态成员函数。 7. 静态成员也是类的成员,也受访问限定符的限制。 8. 静态成员变量不能在声明位置给缺省值初始化,因为静态成员变量不属于某个具体的对象,不走构造函数初始化列表。

代码语言:javascript代码运行次数:0运行复制
#include<iostream>
using namespace std;

class A
{
public:
	A()
	{
		++_scount;
	}
	A(const A& t)
	{
		++_scount;
	}
	~A()
	{
		--_scount;
	}
	static int GetACount()
	{
		return _scount;
	}
private:
	// 静态成员变量在类里面声明
	static int _scount;
};

//静态成员变量在类外面初始化
int A::_scount = 0;

int main()
{
	cout << A::GetACount() << endl;
	A a1, a2;
	A a3(a1);
	cout << A::GetACount() << endl;
	cout << a1.GetACount() << endl;
	return 0;
}
//0
//3
//3

致谢

感谢您花时间阅读这篇文章!如果您对本文有任何疑问、建议或是想要分享您的看法,请不要犹豫,在评论区留下您的宝贵意见。每一次互动都是我前进的动力,您的支持是我最大的鼓励。期待与您的交流,让我们共同成长,探索技术世界的无限可能!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。 原始发表:2025-04-04,如有侵权请联系 cloudcommunity@tencent 删除变量对象函数c++int