c++和注入的基名称

c++ and injected base name

本文关键字:注入 c++      更新时间:2023-10-16

以下代码不在gcc:中编译

namespace One{
   class A{
   };
};
namespace Two{
   class A{
      public:
         void what(){
            cout << "Two::A says what!" << endl;
         }
   };
   class B : public One::A{
      public:
         B(){
            A xx;
            xx.what();
         }
   };
};

它给出了:

gccbug.cpp: In constructor ‘Two::B::B()’:
gccbug.cpp:23: error: ‘class One::A’ has no member named ‘what’

现在,我被告知这是正确的行为(由于注入的基础名称One::A使A引用One::A)。然而,这段代码是用C#编译的(好吧,在更改了一些内容之后),所以这似乎是特定于C++的。

我想知道的是…为什么?将基名称"One::a"注入为"a"是否有特定目的?

我能想到的唯一原因是,在C++中,你可能会在构造函数的初始值设定项列表中引用基类名称,如下所示:

namespace Two {
  /*...*/
  class B : public One::A {
  public:
     B():A()
     {
        /*...*/
     }
   };
}

当然,这样做的目的与您的示例中的目的不同,因为您实际上在构造函数中声明了一个局部变量,而在我的示例中,A()指的是A类型的对象,由于继承,该对象在class B的定义中是隐式的。

然而,我的例子中的情况更有可能发生,所以我想他们认为在这种情况下,我们不需要显式地设置名称空间。因此,对没有命名空间的A的任何引用都被解释为引用基类,而不是任何其他名为A的类,即使它与B的声明在同一命名空间中也是如此。

将基名称"One::a"注入为"a"是否有特定目的?

是的。这样你就可以写下:

namespace N
{
   class A
   {
       A *a;
   };
}

在没有注入名称的情况下,必须编写N::A *a,这并不好。

请注意,这是因为注入的名称,允许使用以下行:

A::A *a1; //ok
A::A::A *a2; //ok 
A::A::A::A *a3; //ok 
A::A::A::A::A *a4; //ok 
//and so on

在线演示

通过用One::限定A,您在作用域中添加了来自namespaceA,因此编译器将在那里查找其名称解析。