5.7 类的作用域
类的作用域简称类域,是指在类的定义中由一对花括号括起来的部分。每一个类都具有该类的类域,该类的成员属于该类的类域中。从前面讲述的类的定义中可知,在类域中可以说明变量,也可以说明函数。从这一点上看,类域与文件域很相似。然而,类域又不同于文件域,在类域中说明的变量不能使用 auto
、register
和 extern
等修饰符,只能用 static
修饰符,而说明的函数也不能用 extern
修饰符。
文件域中可以包含类域,显然,类域小于文件域。一般来说,类域中可包含成员函数的作用域,类域又比函数域大。例如,一个被包含在某个文件域中的类的定义如下所示:
class A {
public:
A(int x, int y) : X(x), Y(y) {}
int Xcoord() { return X; }
int Ycoord() { return Y; }
void Move(int dx, int dy);
private:
int X, Y;
};
int X, Y;
void A::Move(int dx, int dy) {
X += dx;
Y += dy;
}
类 A
的作用域是由类 A
的类体所组成的。其中,成员函数 Move()
声明在类体内,但它的作用域属于类 A
的类域。
由于类中成员的特殊访问规则,使得类中成员的作用域有以下几个特点:
-
成员在成员函数中的作用域:
- 成员函数中的成员变量,如果没有定义同名的标识符,则在成员函数中具有类的作用域。
-
对象的成员表达式中的作用域:
- 当使用类的对象调用成员变量时,该成员变量具有类的作用域。例如,
a.M
中,a
是类A
的对象,M
是类的成员。
- 当使用类的对象调用成员变量时,该成员变量具有类的作用域。例如,
-
指向对象指针的成员表达式中的作用域:
- 当使用指向类对象的指针调用成员变量时,该成员变量具有类的作用域。例如,
Pa
是一个指向类A
的对象的指针,在表达式Pa->M
中,M
是类的成员。
- 当使用指向类对象的指针调用成员变量时,该成员变量具有类的作用域。例如,
-
使用作用域运算符的成员表达式中的作用域:
- 使用作用域运算符限定的成员变量具有类的作用域。例如,在表达式
A::M
中,M
是类的成员。
- 使用作用域运算符限定的成员变量具有类的作用域。例如,在表达式
2024/6/27日补充
今天在看5.3 对象初始化的时候再看这段代码忘记了TDate ::这个运算符号什么意思
TDate::TDate(int y, int m, int d) {
year = y;
month = m;
day = d;
std::cout << "Constructor called." << std::endl;
}
解答:
在C++中,双冒号 ::
是作用域解析运算符(Scope Resolution Operator)。它用于指明某个名称所属的作用域,主要用于以下几种情况:
- 类的成员函数定义:
- 用于在类外定义成员函数,指明该成员函数属于哪个类。
- 命名空间中的成员:
- 用于访问命名空间中的变量、函数或类。
- 枚举中的枚举值:
- 用于访问枚举类型中的枚举值。
- 全局作用域中的名称:
- 用于访问全局作用域中的变量或函数。
类的成员函数定义
在你的例子中,TDate::TDate(int y, int m, int d)
中的 ::
用于指明这个构造函数属于 TDate
类。类的成员函数可以在类的内部声明,在类的外部定义,这时就需要用到 ::
来明确该成员函数属于哪个类。
示例代码
class TDate {
private:
int year;
int month;
int day;
public:
TDate(int y, int m, int d); // 构造函数声明
};
// 构造函数定义
TDate::TDate(int y, int m, int d) {
year = y;
month = m;
day = d;
std::cout << "Constructor called." << std::endl;
}
解释
-
声明:
class TDate { private: int year; int month; int day; public: TDate(int y, int m, int d); // 构造函数声明 };
在类的声明中,只声明了构造函数
TDate(int y, int m, int d)
,并没有具体定义它的实现。 -
定义:
TDate::TDate(int y, int m, int d) { year = y; month = m; day = d; std::cout << "Constructor called." << std::endl; }
在类的外部,用
TDate::TDate(int y, int m, int d)
来定义构造函数。这表示TDate
类的构造函数,其参数为int y, int m, int d
。
其他用法示例
命名空间中的成员
namespace MyNamespace {
void myFunction() {
std::cout << "Hello, World!" << std::endl;
}
}
// 在命名空间外定义函数
void MyNamespace::myFunction() {
std::cout << "Hello, World!" << std::endl;
}
枚举中的枚举值
enum Color {
RED,
GREEN,
BLUE
};
Color myColor = Color::RED;
全局作用域中的名称
int x = 10;
namespace MyNamespace {
int x = 20;
void myFunction() {
int x = 30;
std::cout << ::x << std::endl; // 输出 10,全局作用域的 x
}
}
总结
在你的代码中,TDate::TDate(int y, int m, int d)
中的 ::
用于指明这个构造函数是 TDate
类的成员函数。作用域解析运算符 ::
用于明确命名空间、类、枚举等不同作用域中的成员的所属关系,是C++中非常重要的语法元素。
示例代码
#include <iostream>
class A {
public:
A(int x, int y) : X(x), Y(y) {}
int Xcoord() { return X; }
int Ycoord() { return Y; }
void Move(int dx, int dy);
private:
int X, Y;
};
void A::Move(int dx, int dy) {
X += dx;
Y += dy;
}
int main() {
A a(10, 20);
a.Move(5, 10);
std::cout << "X = " << a.Xcoord() << ", Y = " << a.Ycoord() << std::endl;
return 0;
}
输出结果
X = 15, Y = 30
说明
在这个例子中,A
类的成员函数 Move()
修改了对象 a
的私有成员 X
和 Y
的值。尽管 Move()
函数在类体外定义,但由于它是类 A
的成员函数,因此它可以访问 A
类的私有成员 X
和 Y
。
一般来说,类域介于文件域和函数域之间。由于类域问题比较复杂,在前面和后面的程序中都会遇到,因此只能根据具体问题具体分析。理解类的作用域有助于编写更安全、更高效的代码。