Разница между «объявлением типа» и «объявлением класса» - PullRequest
1 голос
/ 01 ноября 2011

Вопрос довольно простой. Чтобы уточнить, в чем именно заключается разница между Foo1 и Foo2 в приведенном ниже коде с точки зрения способа их объявления (например, один использует class Foo1 { ... };, а другой - typedef class { ... } Foo2;)?

class Foo1 {
public:
    void bar() { }
};

typedef class {
public:
    void bar() { }
} Foo2;

int main()
{
    Foo1 f1;
    f1.bar();
    Foo2 f2;
    f2.bar();
    return 0;
}

Ответы [ 2 ]

6 голосов
/ 01 ноября 2011

Разница тонкая. В первом случае вы создаете класс с именем Foo1, а во втором случае вы создаете анонимный класс и используете typedef для предоставления псевдонима Foo2.

Третий вариант будет:

typedef class Foo3 {
public:
   void bar() {}
} Foo3;

Это создаст класс с именем Foo3 , а создаст псевдоним Foo3 для ссылки на него.

Тонкости заключаются в том, как идентификаторы обрабатываются в языке. Когда в коде присутствует идентификатор, компилятор выполнит поиск, чтобы знал , что это значит. Поиск будет проверяться в каждой области видимости, сначала в глобальном идентификаторе , где определено большинство символов (исключая определенные пользователем типы), и если ему не удается найти идентификатор, он затем просматривает пользователя определяемое пространство идентификаторов . Определяемые пользователем типы принадлежат второму пространству идентификаторов, в то время как typedef -значные имена присутствуют в первой группе. Только если оба поиска завершатся неудачно, компилятор перейдет к следующей закрывающей области видимости.

Чтобы предоставить простой тестовый пример, в котором различия заметны:

class A {};
typedef class {} B;
typedef class C {} C;
void A();              // correct: no collision
//void B();            // error, identifier B already used with a different meaning!
//void C();            //   "
namespace test {
   void B();
   void C();
   void f() {
      class A a;       // creates variable of type ::A
      A();             // calls function ::A
      B();             // calls function test::B()
      //class B b;     // error: B does not denote a user-defined type name
      C();             // calls function test::C()
      class C c;       // creates variable of type ::C
   }
}
0 голосов
/ 01 ноября 2011

Я полагаю, что второй был необходим для C, но действительно не нужен для C ++. Внутренне я верю, что второй создает неназванный класс, а затем создает typedef для этого, в то время как первый просто создает класс.

Я не думаю, что объявление класса стиля typedef необходимо в библиотеках c ++.

...