c ++ и введенное базовое имя - PullRequest
6 голосов
/ 26 февраля 2012

Следующий код не компилируется в 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»?

Ответы [ 3 ]

3 голосов
/ 26 февраля 2012

Единственная причина, по которой я могу придумать, состоит в том, что в C ++ вы, вероятно, будете ссылаться на имя базового класса в списке инициализатора конструктора, например так:

namespace Two {

  /*...*/

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

Конечно, цель в том, чтобыотличается от того, что в вашем примере, потому что вы фактически объявляете локальную переменную внутри конструктора, тогда как в моем примере A() относится к объекту типа A, который неявно присутствует в определении class B из-за наследования.

Однако ситуация с моим примером более вероятна, поэтому я думаю, они подумали, что давайте не будем требовать явного указания пространства имен в этом случае.Как следствие, любая ссылка на A без пространства имен интерпретируется как ссылка на базовый класс, а не на любой другой класс с именем A, даже если он находится в том же пространстве имен, что и объявление B.

3 голосов
/ 26 февраля 2012

Есть ли конкретная цель для введения базового имени "One :: A" как "A"?

Да. Это так, чтобы вы могли написать это:

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

При отсутствии введенного имени, вы должны написать N::A *a, что нехорошо.

Обратите внимание, что из-за injected-name допускаются следующие строки:

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

Демо онлайн

0 голосов
/ 26 февраля 2012

Квалифицируя A с One::, вы добавили A из namespace в область видимости, поэтому компилятор будет искать его разрешение имен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...