06-6 继承同名静态成员处理方式
-
复习:
静态成员:静态成员分为:
- 静态成员属性(在成员变量前加上
ststic
)- 所有对象共享一份数据;
- 在编译阶段分配内存(一般的数据存放在栈区)
- 类内声明,类外初始化
- 静态成员函数(在成员函数前加上
ststic
)- 所有对象共享同一个函数
- 静态成员函数只能访问静态成员变量。
- 静态成员属性(在成员变量前加上
思考:继承中同名的静态成员如何在子类对象上进行访问。
#include <iostream>
#include <string>
using namespace std;
class A
{
public:
static string STR;
static void STRF()
{
cout << "这是类 A 的静态成员函数" << endl;
}
};
class B :public A
{
public:
static string STR;
static void STRF()
{
cout << "这是类 B 的静态成员函数" << endl;
}
};
string A::STR = "这是类 A 的静态成员属性";
string B::STR = "这是类 B 的静态成员属性";
int main()
{
cout << B::A::STR << endl;
cout << B::STR << endl;
B::A::STRF();
B::STRF();
class B p;
cout << p.STR << endl;
cout << p.A::STR << endl;
p.STRF();
p.A::STRF();
return 0;
}
运行结果:(环境:Windows11(arm/Apple M VM)/Visual Studio 2022/Debug/arm64)
这是类 A 的静态成员属性
这是类 B 的静态成员属性
这是类 A 的静态成员函数
这是类 B 的静态成员函数
这是类 B 的静态成员属性
这是类 A 的静态成员属性
这是类 B 的静态成员函数
这是类 A 的静态成员函数
我们来分析一下:
在这里,我们创建了两个类,一个类是类A
,另外一个是类B
。其中,类B
使用公共继承方式(public
)继承自类 A
。
在类A
和类B
中,分别都有一个一个静态成员属性STR
和静态成员函数STRF
。由于是STR
是静态的成员属性,所以需要在类内声明,在类外使用数据类型 作用域::变量名称 = 初始值
的方式进行赋初始值的操作。
之后我们使用两种方式进行访问继承类中的同名静态成员。
-
使用作用域直接访问。
由于这些是静态的成员,所有的类的对象共享一份数据,所以我们可以直接用
作用域::静态成员名称
的方式进行访问。比如:
cout << B::A::STR << endl;
打印B
类中继承自A
类的静态成员属性STR
,当然,这一句也可以简写为:cout << A::STR << endl;
。cout << B::STR << endl;
就是访问B
类中的静态成员属性。同理,
B::A::STRF();
,调用B
类中继承自A
类的静态成员函数STRF
,可以简写为A::STRF();
。B::STRF();
就是调用B
类中的静态成员函数。请注意,由于是静态成员的调用,在不创建对象的情况下,必须要使用作用域的方式才可以访问。所以,如果需要调用
A
类的静态成员,没必要先从子类中再去访问父类,可以直接从父类调用。 -
使用子类的对象进行访问。
静态成员也可以使用对象进行访问。我们创建了一个类
B
的对象p
。可以使用p.STR
和p.STRF()
直接访问类B
的静态成员。但是如果需要访问继承的类A
的静态成员,则需要加上作用域,比如:p.A::STR
、p.A::STRF();
。对于使用子类对象访问静态成员的方法,其实和普通成员的访问方法一样,都是增加作用域即可访问。
综上,我们可以得出:如果子类中出现了和父类同名的静态成员,子类同名静态成员会默认隐藏掉父类的同名静态成员。如果需要访问父类的被隐藏的同名静态成员,需要加上作用域。
- 总结:
- 继承中的同名静态成员的访问和同名成员一样,都是添加作用域来实现访问。
- 由于静态成员的特殊性(所有的类的对象共享一份静态成员,静态成员存储在内存的全局区),所以也可以不创建类的对象直接使用作用域来访问。
- 请注意,静态成员属性需要在类内声明,但是必须在类外赋值(初始化)。
:-)