3

我在 A 类中有一个静态成员变量,B 类派生自 A 类。

class A
{
  public:
    A()
    {
      a = 3;
    }
    static int a;
};

int A::a = 0;

class B : public A
{
  public:
    B()
    {
      a = 4;        
    }
};

void main()
{
  A objA;
  cout << "Before:" << A::a;
  B obj;
  cout << endl << "After:" << A::a;
}
     

根据静态字段是否继承?当创建派生类型对象时,它也会创建基类型。我有以下问题:

  1. 怎么不是A::a我也可以访问objA.a?不应通过该类的对象访问静态变量。

  2. 如果对于派生类也创建了一个新的静态变量(特定于class B),那么为什么不需要初始化静态变量class B呢?

  3. 为什么以下输出显示为:

之前:3

之后:4

预计什么时候会在前后显示 3?

4

5 回答 5

4

对静态变量的访问是继承的。请注意,具有私有访问权限的静态成员将无法访问,因为这就是protected关键字的用途。

于 2013-05-08T17:09:29.993 回答
3
  1. 没有 objA.a,可以访问内部 B() 构造函数,其中 A::a 是可见的,因此可以仅作为“a”访问。

  2. B::a 指的是内存中的同一个地址,B::a 没有新的静态变量,可以通过 &B::a 来检查。

  3. 预计不会是 3 和 3,预计会是 3 和 4,因为“B obj;”行 更改 A::a 值,并且由于 (2) 它与 B::a 相同的变量(即 B() 构造函数更改 A::a)。

于 2013-05-08T17:14:49.743 回答
2

您的根本问题是您错误地解释了您链接的问题的答案。当您派生类时,B不会创建新的静态变量a

所以A::aB::a是同一个变量。一旦你纠正了这种误解,其他一切都将是显而易见的。

查看您的代码:

A objA; //A() executes which sets A::a to 3
cout << "Before:" << A::a; //outputs 3
B obj; //now B() executes and sets B::a to 4
cout << endl << "After:" << A::a; //outputs 4 since A::a is same variable as B::a

为什么我也可以访问 objA.a 而不是 A::a?

因为语言规范说你可以。语言规范说,A::a并且objA.a是同一个变量。这在任何好的语言指南中都有介绍。例如,您可以在线阅读cppreference.com,它是这样说的:

要引用类 T 的静态成员 n,可以使用两种形式:限定名称 T::m 或成员访问表达式 em 或 e->m,其中 e 是分别计算为 T 或 T* 的表达式。在同一类范围内时,资格是不必要的。

于 2013-05-08T17:12:40.407 回答
0

静态成员是继承的吗?

从某种意义上说,基类的静态成员也是任何派生类的静态成员,是的。

怎么不是A::a我也可以访问objA.a。不应通过该类的对象访问静态变量。

这就是语言的定义方式。两者是等价的,如果不能轻易写出对象的类型,对象样式会更方便。

如果为派生类也创建了一个新的静态变量(特定于 B 类),那么为什么不需要为 B 类初始化静态变量?

没有特定于 class 的新静态变量B;只有一个班级A。继承意味着它也在 class 范围内B;但是A::a两者B::a都引用同一个变量。

为什么在预期之前和之后显示 3 时,以下的输出显示为 [3,4]?

如上所述,只有一个变量,构造函数B将其设置为4

于 2013-05-08T17:20:06.277 回答
0
  1. 静态变量可以通过该类的对象访问。他们为什么不呢?
  2. 任何静态变量都只有一份副本。如果另一个类继承它,它只能访问同一个静态变量,而不是另一个副本。
  3. 因为B::B()更改A::a为 4.BA共享访问权限A::a
于 2013-05-08T17:14:19.417 回答