2021-10-17


前言

接上一篇内容。本节是讲解类作用域,包括块作用域、文件作用域、函数原型作用域、函数作用域、类作用域

一、类作用域

1.作用域

代码如下(示例):

#include <iostream>
using namespace std;
class Test
{
public:
	int num_;//作用域在类范围内,称为类作用域
};
//num_=20 Error 类外部不可以赋值
int num_ = 20;//True,作用域是文件作用域,与类中的num_不同作用域
int add(int a, int b);//a,b两个标识符的作用域为函数原型作用域

int main(void)
{
	int num_;//块作用域
	{
		int num_ = 100;//也是块作用域,不影响外部作用域
	}

	cout << num_ << endl;
	cout << ::num_ << endl;//文件作用域中的num_变量
	return 0;

}


int add(int a, int b)//形参也属于块作用域
{
	return a + b;

}

int test()
{
LABEL1://三个标签是函数作用域,在函数内部是有效的
	cout << "label1" << endl;
	goto LABEL3;
LABEL2:
	cout << "label2" << endl;
LABEL3:
	cout << "label3" << endl;
}

2.前向声明

C++中必须先定义,才能够实例化。
两个类需要相互引用形成一个环形引用时,无法先定义使用。这时候需要使用到前向声明
⭐前向声明的类不能实例化。

//相互包含时不成立的,出现错误,需要用到前向声明

class A {
public:
	A(void);
	B b_;//包含B头文件
};

class B {
public:
	B(void);
	A a_;//包含A头文件
};

3.嵌套类

1.从作用域的角度看,嵌套类被隐藏在外围类之中,该类名只能在外围类中使用。如果在外围类的作用域使用该类名,需要加名字限定。
2.外围类不能访问嵌套类的私有成员,同样嵌套类也不能访问外围类的私有成员。
⭐举例
	void Outer::Iner::Fun()
{
	cout << "Inner::Fun…" << endl;

}
#include <iostream>
using namespace std;
class Outer
{
	class Iner {
	public:
		void Fun() {
			cout << "Iner::Fun…" << endl;
		}
	};
public://嵌套类为外围提供服务
	Iner obj_;
	void Fun()
	{
		cout << "Outer::Fun…" << endl;
		obj_.Fun();
	}

};
int main(void)
{
	Outer o;
	o.Fun();
	return 0;

}

在这里插入图片描述

4.局部类

局部类中不能有静态成员。

void Fun()
{
	class LocalClass//局部类只能在函数内有效
	{
	public:
		int num_;
		void Init(int num)
		{
			num_ = num;
		}
		void Display()
		{
			cout << "num=" << num_ << endl;
		}
	
	};

	LocalClass lc;
	lc.Init(10);
	lc.Display();
}

二、构造函数和析构函数

1.构造函数

构造函数是特殊的成员函数。创建类类型的新对象,系统自动会调用构造函数,构造函数是为了保证对象的每个数据成员都被正确初始化。

1.函数名与类名完全相同
2.不能定义构造函数的类型,也不能使用void
3.通常情况下构造函数应声明公有函数,否则它不能像其他成员函数那样被显式调用
4.⭐构造函数允许被重载,构造函数可以有任意类型和任意个数的参数,一个类可以有多个构造函数(重载)。
5.不带参数的构造函数,系统会自动产生一个默认的构造函数
//头文件Test.h
#ifndef  _TEST_H_
#define  _TEST_H_
class Test
{
public:
	Test();
private:
	int num_;
};
#endif // ! _TEST_H_
//构造函数Test.cpp
#include"Test.h"
#include <iostream>
using namespace std;

Test::Test()
{
	num_ = 0;
	cout << "Initializing Default" << endl;
}

在这里插入图片描述

class Test
{
public:
	Test();//重载
	Test(int num);
	//如果类不提供任何一个构造函数,系统将为我们提供一个不带参数的默认的 构造函数
	void Display();
private:
	int num_;
};

在这里插入图片描述

2.构造函数和new运算符

int main(void)
{//构造函数自动被调用
	Test t;
	t.Display();
	Test t2(10);//类定义了一个对象,新建一个对象时函数被调用输出
	t2.Display();

	Test* t3 = new Test(20);//new operator不仅仅分配了内存,还调用了构造函数
	t3->Display();

	delete t3;//不仅释放内存,还调用了析构函数
	return 0;

}

3.全局对象的构造先于main函数

代码如下(示例):

#include"Test.h"
#include<iostream>
using namespace std;

Test t(10);

int main(void)
{
	cout << "Entering main…" << endl;
	cout << "Exiting main…  " << endl;
	return 0;
}

在这里插入图片描述

4.析构函数

1.函数名与类名相似(前面多了一个字符“~”)
2.没有返回类型  没有参数  析构函数不能被重载
3.没有定义析构函数,编译器会自动生成一个默认析构函数,其格式如下:
   类名::~默认析构函数名(){}

析构函数与数组的关系
Test* t2 = new Test(2);
	delete t2;
#include"Test.h"
#include<iostream>
using namespace std;

int main(void) {
	Test t[2] = { 10,20 };//两个对象,调用两次构造函数
	return 0;
}

在这里插入图片描述

delete不仅仅释放内存还调用了析构函数
int main(void) {
	Test t[2] = { 10,20 };//两个对象,调用两次构造函数

	Test* t2 = new Test(2);
	delete t2;

	Test* t3 = new Test[2];
	delete[] t3;

	return 0;
}

在这里插入图片描述

总结

构造函数是一种特殊的成员函数
在创建对象的时候自动调用,对对象的数据成员进行初始化

栈区中创建的对象,在生存期结束时会自动调用析构函数
在堆上创建的对象,要有程序员显式的调用delete释放该对象,同时调用析构函数

全局对象的构造先于main函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值