第三章:03类和对象


代码运行环境

本节教程所有代码都是在win11系统,Qt 5.12.12版本,mingw编译工具环境编写运行。创建的工程类型为Qt Console Application。


1.类作用域

每个类都定义了自己的作用域,称为类作用域。类作用域中说明的标识符只在类中可见。

  • 块作用域:花括号以内的范围
int main(int argc, char *argv[])
{
   QCoreApplication a(argc, argv);
   int aa = 30;  //属于块作用域
   {
       int aa = 100;  //属于块作用域内,并不会和函数中的aa出现命名冲突
   }

   return a.exec();
}

  • 文件作用域:在代码文件中但是不在任何括号内的区域。作用域为在变量刚声明到文件结尾。要调用文件作用域的变量,应该用这种方式: ::文件域变量
#include <QCoreApplication>
#include <iostream>
using namespace std;
int num = 20;   //这个作用域称为文件作用域
int main(int argc, char *argv[])
{
   QCoreApplication a(argc, argv);
   cout << ::num << endl;    //调用文件域变量
   return a.exec();
}
  • 函数原型作用域:
#include <QCoreApplication>
#include <iostream>
using namespace std;

int add(int a, int b); //a,b两个标识的作用域为 函数原型作用域
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    add(12,12);
    return a.exec();
}

int add(int a, int b) //形参a,b属于块作用域
{
    cout << a + b << endl;
    return a + b;
}
  • 函数作用域:针对goto语句来所
#include <QCoreApplication>
#include <iostream>
using namespace std;

int add(int a, int b); //a,b两个标识的作用域为 函数原型作用域
int main(int argc, char *argv[])
{
   QCoreApplication a(argc, argv);
   add(12,12);
   return a.exec();
}
int test()
{
   LABEL1:
   cout << "label1" << endl;
   goto LABEL2;   //对于这句代码,goto并不知道LABEL2是否声明,
                  //但是由于LABEL2属于函数作用域,这段代码没有问题
   LABEL2:
   cout << "label2" << endl;
   goto LABEL2;
}
  • 类作用域:类的花括号以内的范围

2.前向声明

C++中类必须先定义,才能够实例化。但是如果存在两个类需要相互引用形成一个“环形”引用的情况,无法先定义使用。这时候需要用到前向声明。前向声明的类不能实例化
环形引用代码如下:

#ifndef A_H
#define A_H
//A类中声明一个B类对象,同时B类中声明一个A类对象,这种现象属于环形引用
//在编译的时候会提示错误,这就需要用到前向声明
#include "b.h"

class A
{
public:
    A();
    B b; //A类中声明一个B类对象
};

#endif // A_H

#ifndef B_H
#define B_H
#include "a.h"
class B
{
public:
    B();
    A aa;  //B类中声明一个A类对象
};

#endif // B_H

前向声明代码如下:

#ifndef A_H
#define A_H
#include "b.h"

class A
{
public:
    A();
    B b; //A类中声明一个B类对象
};

#endif // A_H

//在B类中对A类使用前向声明
#ifndef B_H
#define B_H
//需要去掉这句
//#include "a.h"
//添加前向声明
class A;
class B
{
public:
    B();
    //A aa;  对A进行前向声明后不能定义对象
    //只能定义指针,但是在B.cpp中使用A的指针,则需要声明A.h
    A* aa;
    // void fun(A a); 这样也不行,只能是引用和指针作为参数
};

#endif // B_H

3.嵌套类

外围类需要使用嵌套类对象作为底层实现,并且该嵌套类只用于外围类的实现,且同时可以对用户隐藏该底层实现。嵌套类中的成员函数可以在它的类体外定义。

#include <iostream>
using namespace std;

class Outer
{
	//这是嵌套类
	class Inner
	{
	public:
		void Fun()
		{
			cout <<"Inner::Fun..." << endl;
		}
		
	};
public:
	Inner mInner;
	void Fun()
	{
		cout <<"Inner::Fun..." << endl;
		mInner.Fun();
		mInner.Fun2();
	}
}
//在文件作用域实现嵌套类函数
void Outer::Inner::Fun2()
{
	cout <<"Inner::Fun2..." << endl;
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    Outer o;
    o.Fun();
    return a.exec();
}

从作用域的角度看,嵌套类被隐藏在外围类中,该类名只能在外围类中使用。如果在外围类的作用域使用该类名时需要加名字限定。嵌套类的成员函数对外围类的成员没有访问权限,反之亦然。嵌套类仅仅只是语法上的嵌入

4.局部类

定义在函数体中的类称为局部类(local class)。局部类只在定义它的局部域内可见。局部类的成员函数必须被定义在类体中。局部类中不能有静态成员

#include <iostream>
using namespace std;

class Outer
{
	//这是嵌套类
	class Inner
	{
	public:
		void Fun()
		{
			cout <<"Inner::Fun..." << endl;
		}
		
	};
public:
	Inner mInner;
	void Fun()
	{
		cout <<"Inner::Fun..." << endl;
		mInner.Fun();
		mInner.Fun2();
	}
}
//在文件作用域实现嵌套类函数
void Outer::Inner::Fun2()
{
	cout <<"Inner::Fun2..." << endl;
}

//定义一个全局函数,里面再定义一个类
void Fun()
{
	//定义一个局部类
	class LocalClass 
	{
	public:
		int mNum;
		// static int smNum; 这样是错的,不能定义静态变量  
		void Init(int num)
		{
			mNum = num;
		}
		void Display()
		{
			cout << "num= " << mNum;
		}
		
	};
	//局部类只能在函数内部使用
	LocalClass lc;
	lc.Init(10);
	lc.Display();
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    Fun();
    return a.exec();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值