класс — Как это можно использовать в C ++?

  1. К моему удивлению, я обнаружил, что имя объекта c ++ может совпадать с именем класса. Может кто-нибудь объяснить мне причину?
  2. Когда я объявляю объект класса a как a a1(), это не вызывает ошибку, но не вызывает конструктор. Почему это происходит?

Мой код:

#include<iostream>
using namespace std;

class a
{
public:
a()
{
cout << "in a\n";
}
};

int main()
{
a a1();
a a;
}

17

Решение

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

a a1;

правильно вызовет конструктор по умолчанию

Когда ты пишешь a a; это работает, потому что имя переменной имеет преимущество перед именем класса в том, что называется скрытием имени, но даже если это работает, это только приведет к путанице, и я бы избегал этого.

И для всех тех, кто любит стандарты цитаты здесь вы идете

Имя класса (9.1) или имя перечисления (7.2) может быть скрыто по имени переменной, члена данных, функции или перечислителя, объявленных в той же области. Если имя класса или перечисления и переменная, член данных, функция или перечислитель объявлены в одной и той же области (в любом порядке) с одинаковым именем, имя класса или перечисления будет скрыто везде, где переменная, член данных, функция или Имя перечислителя видно.

20

Другие решения

a a1(); это объявление функции.

Это важная причина для создания единой инициализации в C ++ 11. Чтобы инициализировать объект с помощью конструктора в C ++ 11, используйте a a1{};

8

На самом деле, если вы посмотрите на C ++ черновик стандартного раздела 3.3.10 Имя скрывается параграф 2 говорит (акцент мой):

Имя класса (9.1) или имя перечисления (7.2) может быть скрыто по имени переменной, элемент данных, функция или перечислитель, объявленные в той же области видимости. Если имя класса или перечисления и переменная, член данных, функция или перечислитель объявлены в одной и той же области (в любом порядке) с одинаковым именем, имя класса или перечисления будет скрыто везде, где переменная, член данных, функция или имя перечислителя
видимый.

Я не думаю, что это хорошая практика, и это приведет к трудностям в поддержании кода. Эта строка кода фактически объявляет функцию:

a a1();

Вы можете альтернативно использовать этот предварительныйC ++ 11:

a a1 ;

или же равномерная инициализация введено в C ++ 11 :

a a1{} ;

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

int main()
{
a a;
a a2 ;
}

Я получаю это сообщение:

main.cpp:12:10: note: class 'a' is hidden by a non-type declaration of 'a' here
a a;
^

хотя я не вижу, чтобы получить подобное предупреждение от gcc,

Обновить

Думая об этом комментарии, которые я сделал ранее бородавки равномерной инициализации, Я понял, что ты подозревал, что a1 был как-то не тот тип, который вы могли бы использовать TypeId отладить то, что происходило. Например этот код:

std::cout << typeid(a).name() << std::endl ;
std::cout << typeid(a1).name() << std::endl ;

результаты в этом выводе на Coliru живой пример:

1a
F1avE

и проходя через C ++ ФИЛТР Вы получаете этот вывод:

a ()     // A function that returns type a
a        // type a
4

a a1(); является типом возврата объявления функции как a который не имеет ничего общего с вызывающим конструктором

a a ; простое утверждение отлично работает вызовет конструктор

0

Это то, что я получил из вашего кода, когда пытался скомпилировать его с clangЯ думаю, это говорит обо всем.

test.cpp:15:9: warning: empty parentheses interpreted as a function declaration
[-Wvexing-parse]
a a1();
^~
test.cpp:15:9: note: remove parentheses to declare a variable
a a1();
^~
1 warning generated.
0
По вопросам рекламы [email protected]