C++类和对象(下)

文章详细探讨了C++中的构造函数,包括构造函数体赋值和初始化列表的使用。接着介绍了静态成员的概念和特性,如它们是类共享的,并需要在类外初始化。此外,文章还讨论了友元,包括友元类和友元函数,以及内部类和匿名对象的应用。

目录

一、深究构造函数

1.构造函数体赋值

2.初始化列表

二、static成员

1.概念

 2.特性

三、友元

1.友元类

2.友元函数

 四、内部类

五、匿名对象


一、深究构造函数

1.构造函数体赋值

在创建对象时,编译器通过调用构造函数,给对象中各个成员变量一个合适的初始值。

class Date
{
public:
	Date(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;
};

这样虽然在调用构造函数之后,对象有了初始值,但是并不能将其称为对象成员的初始化,实际上是给已经存在的成员变量赋值,而不是对其成员变量进行初始化。初始化只能在对象创建时进行一次,而赋值操作可以在构造函数体内进行多次。

2.初始化列表

初始化列表位于构造函数的冒号后面,后面跟着成员初始化列表。每个成员初始化由成员变量名和对应的初始化值组成,用逗号分隔

class Date
{
public:
	Date(int year, int month, int day)
		:_year(year)
		,_month(month)
		,_day(day)
	{}
private:
	int _year;
	int _month;
	int _day;
};

[注意]
1.每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次)

2.类中包含以下成员,必须放在初始化列表位置进行初始化:
引用成员变量
const成员变量
自定义类型成员(且该类没有默认构造函数时)

3.成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关

上述所说初始化列表既然已经这么好用,那么我们在写程序时候还需要用函数体赋值吗?

答案是:存在即合理(需要)

例如:申请动态内存检查这样复杂的操作是需要在函数体内完成的

二、static成员

1.概念

静态成员是属于类而不是类的实例的成员。它们在类的所有实例之间共享,并且可以在没有类的实例的情况下访问。


class EG
{
public:
	EG()
	{
		_count++;
	}
	EG(const EG& a)
	{
		_count++;
	}
	~EG()
	{
		_count--;
	}
	static int GetCount()
	{
		return _count;
	}
private:
	static int _count;
};
//类外进行初始化
int EG::_count = 0;

EG a1;
int main()
{
	cout << __LINE__ << ":" << EG::GetCount() << endl;
	EG a2;
	cout << __LINE__ << ":" << EG::GetCount() << endl;
	static EG a3;
	cout << __LINE__ << ":" << EG::GetCount() << endl;
	return 0;
}

上图运行结果

 2.特性

1.静态成员为所有类对象所共享,不属于某个具体的对象,存放在静态区

2.静态成员变量必须在类外定义,定义时不添加static关键字,类中只是声明

3.类静态成员即可用类名::静态成员或者对象静态成员来访问

4.静态成员函数没有隐藏的this指针,不能访问任何非静态

5.成员静态成员也是类的成员,受public、protected、private 访问限定符的限制

三、友元

C++中,友元是一种机制,允许一个类或函数访问另一个类的私有成员。友元关系通过在类定义中声明其他类或函数为友元来建立。友元可分为友元类友元函数

1.友元类

友元类是指在一个类中声明另一个类为友元。这样,被声明为友元的类可以访问声明类中的私有和受保护成员。

1. 友元关系是单向的,被声明为友元的类不一定将声明类作为友元,也就是说,A类将B类声明为友元类,但B类不会自动将A类声明为友元类。2.

友元关系不能传递,如果A是B的友元,B是C的友元,这不能说明A是C的友元。

​

class EG1
{
	friend class EG2;
public:
	EG1(int a)
		:_a(a)
	{}
private:
	int _a;
};

class EG2
{
public:
	EG2(int b = 0)
		:_b(b)
		,_obj(b)
	{}
	void Test(int x)
	{
		_obj._a = x;
		cout << _obj._a << endl;
	}
private:
	int _b;
	EG1 _obj;
};
int main()
{
	EG2 b(10);
	b.Test(-1);
	return 0;
}

[点击并拖拽以移动]
​


2.友元函数

  • 友元函数是在一个类中声明一个非成员函数为友元。被声明为友元函数的函数可以访问声明类中的私有和受保护成员。
  • 友元函数不是类的成员函数,它可以在类的外部定义。
  • 一个函数可以是多个类的友元函数
class EG
{
	friend void Print(EG& obj);
public:
	EG(int a = 1, int b = 1, int c = 1)
		:_a(a)
		, _b(b)
		, _c(c)
	{}
private:
	int _a;
	int _b;
	int _c;
};

void Print(EG& obj)
{
	cout << obj._a << endl;
	cout << obj._b << endl;
	cout << obj._c << endl;
}
int main()
{
	EG a(1, 2, 3);
	Print(a);
	return 0;
}

 四、内部类

内部类是定义在另一个类的内部。内部类可以访问外部类的私有成员,而外部类不能直接访问内部类的成员。内部类与外部类之间建立了一种特殊的关联关系,内部类可以看作是外部类的成员。

class EG1
{
public:
	class EG2
	{
	public:
		void func()
		{}
	private:
		int __b;
	};
private:
	int _a;
};
int main()
{
	EG1 a;
	cout << sizeof(a) << endl;
	return 0;
}

五、匿名对象

匿名对象主要用于临时的、一次性的操作,避免创建不必要的变量。它们在某些情况下可以提供简洁的语法,并且可以在一行代码中完成特定的操作。

class EG
{
public:
	void Print()
	{
		cout << "hello world" << endl;
	}
};
int main()
{
	EG a;	    //有名对象 -- 生命周期当前函数局部域
	EG().Print();//匿名对象 -- 生命周期当前行
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值