代码运行环境
本节教程所有代码都是在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();
}