boxmoe_header_banner_img

糖画99

文章导读

类和对象(下)


avatar
mizuki 2026年5月28日 21

1.引言

这将是类和对象的最后一篇文章,相信经过最后一篇文章的学习,一定能够加深你对类和对象的理解

2.再探构造函数

  • 2.1初始化列表

在构造函数的函数名后接一个引号“ : ”,然后写需要初始化的成员对象,在成员对象后接括号,括号内是对应成员初始化的值,每个成员的初始化之间用逗号“ , ”相隔,下面将给出一个例子

class A
{
public:
	A(int a, int b) : _a(a),
		_b(b)
	{

	}
private:
	int _a;
	int _b;
};
  • 2.2特点

1.每个成员只能初始化一次

2.每个成员对象都要走初始化列表

3.const类型,引用,和没有默认构造的自定义类型对象只能够在初始化列表中定义,否则会报错

4.尽量使用初始化列表初始化

5.初始化列表初始化的顺序是按照声明的顺序初始化的,而不是定义,给出一个例子

class A
{
public:
	A(int a, int b) : _b(b),
		_a(a)
	{

	}
private:
	int _a;
	int _b;
};

这里初始化的顺序是a->b,而不是b->a

6.构造函数中可以给缺省值,成员对象也可以给缺省值

2.隐式类型转换

1.C++支持内置类型隐式类型转换为类类型对象,需要有相关内置类型为参数的构造函数,多参数的要用{}

2.如果在构造函数前加explict,就可以防止隐式类型转换

3.类类型之间也支持隐式类型转换,但需要相对应的构造函数

这里给出隐式类型转化的例子

class A
{
public:
	A(int a, int b) : _a(a),
		_b(b)
	{

	}
	void Print()
	{
		cout << _a << " " << _b << endl;
	}

	int Get() const
	{
		return _a + _b;
	}
private:
	int _a;
	int _b;
};

class B
{
public:
	B(const A& a) : _a(a.Get())
	{

	}
	void Print()
	{
		cout << _a << endl;
	}
private:
	int _a;
};

int main()
{
	//类类型隐式类型转换
	A a1 = { 1, 2 };
	a1.Print();

	B b1 = a1;
	b1.Print();

	return 0;
}

运行结果如下:

3.static成员

  • 3.1 特点

1.静态成员必须在类外初始化

2.静态成员为所有类对象共享,不专门属于任何一个类对象,放在静态区内

3.静态成员函数无this指针,因此不能访问非静态的对象

  • 3.2 例子
class C
{
public:
	C(int b): _b(b)
	{}

	void Aadd()
	{
		_a++;
	}

	void APrint()
	{
		cout << "_a = " << _a << " ";
		cout << "_b = " << _b << endl;
	}

private:
	static int _a;
	int _b = 3;
};

//在类外进行初始化
int C::_a = 0;

int main()
{
	C a1(2);
	C a2(3);

	a1.APrint();
	a2.APrint();

	//利用a1对静态_a对象++,a2中的_a也会改变
	a1.Aadd();
	a2.APrint();
	return 0;
}

这里给出运行结果:

4.友元

  • 4.1 用法

是一种访问限定符,分为友元函数和友元类,具体用法是将类声明或者函数声明前加“friend”,然后放入需要友元的类中,这样可以访问到成功友元的类中的成员,这里给出一个最经典的例子,也就是<<的重载:

可以看到,这里通过友元的方式,就能直接访问到类中private里的成员对象

  • 4.2 特点

1.可以访问类的私有和保护对象

2.可以在类中的任何位置声明(仅仅只是声明)

3.一个函数可以成为多个类的友元

4.友元类的关系是单向的,不能够传递,尤其是对于友元类来说,这里给出一个例子:

class D
{
	friend class E;
private:
	int _d;
};

class E
{
	friend class F;
private:
	int _e;
};

class F
{
public:
	void PrintD(D d)
	{
		cout << d._d << endl;
	}
private:
	int _f;
};

注意,这里是不能访问到_d的,放在编译器中则可以看到明显的报错:

5.内部类

  • 5.1 定义

一个类定义在另一个类的内部,是一个独立的类,仅仅只是受到了类域限制

  • 5.2 特点

默认内部类是外部类的友元,也就是内部类可以访问外部类的成员,但是同友元类相同,外部类是无法访问内部类的私有和保护成员的,这里给出例子

class H
{
	class h
	{
	public:
		void Print(H a)
		{
			cout << a._H;
		}
	private:
		int _h = 2;
	};

public:
	void Print(h a)
	{
		cout << a._h;
	}
private:
	int _H = 1;
};

当我们把这段代码放进编译器中时,会发现h类中的Print函数是可以正常访问的,但是H类中的函数就不行:

6.匿名对象

  • 6.1 用法

直接写类名+()进行初始化,如下:

class L
{
public:
	L(int l): _l(l)
	{}
	int Get()
	{
		return _l;
	}
private:
	int _l;
};

int main()
{
	cout << L(3).Get() << endl;
	return 0;
}
  • 6.2 意义(特点)

匿名对象是一次性的,生命周期只存在于这一行,通常被使用在调函数和传参中

7.对象拷贝时的编译器优化

  • 7.1 定义

编译器在不影响其正确性的情况下,会减少一些传参和返回值的拷贝,能合并的都会尽量合并,以提高编译的效率,特别是在release版本中

  • 7.2 特点

1.对于传参,可能只产生临时变量,而不进行拷贝

2.不同的编译器的优化是不同的

  • 7.3 特记

因为这个如果要仔细讲的话篇幅很长,所以可以自己下去了解,以后有时间我也会单独写一篇关于编译器优化的文章

8.总结

类和对象篇终于结束,还是用了将近一个周的时间才完成,后续也将会继续整理关于c++学习的文章



评论(0)

查看评论列表

暂无评论


发表评论

表情 颜文字

插入代码