Метод класса и переменная с тем же именем, ошибка компиляции в C++ не в Java?

class Test {

      bool isVal() const {
          return isVal;
      }

  private:

      bool isVal;
};

При компиляции этого файла говорится

testClass.cpp:9: declaration of `bool Test::isVal'

testClass.cpp:3: conflicts with previous declaration `bool Test::isVal()'

Хотя то же самое будет работать для java

class Test {

  private boolean isVal;

  public boolean isVal() {
      return isVal;
  }

}

Почему ошибка компиляции возникает в C++, а не в Java?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
44
0
43 419
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Ответ принят как подходящий

Потому что C++ - это не Java. Вы можете взять адрес участника:

&Test::isVal

Таким образом, у вас не может быть двух членов с одинаковыми именами, за исключением того, что вы можете перегружать функции-члены. Даже если бы вы могли устранить неоднозначность с помощью какого-то актерского состава, следующая проблема уже возникла бы в других местах.

В C++ многие люди, включая меня, обычно специально называют элементы данных, например, ставят m перед своим именем. Это позволяет избежать проблемы:

class Test {
public:
    bool IsVal() const { return mIsVal; }
private:
    bool mIsVal;
};

... и, по сути, у функций все равно разные имена, поскольку они различаются по классу и сигнатуре аргумента.

Charlie Martin 22.01.2009 05:10

В C++ мы обычно вызываем переменные-члены специально, например, ставим m перед их именем ???? Мы делаем? Это в спецификации языка? Это идеальный ответ вплоть до этого предложения и следующего за ним примера.

jmucchiello 22.01.2009 06:45

joe_mucchiello, выйдите и посчитайте все популярные искажения имен, такие как "data_", "_data", "mData", "m_data" и т. д. ... я думаю, это оправдывает мое использование слова «обычно».

Johannes Schaub - litb 22.01.2009 09:52

(IIRC) Microsoft сделала это первой. В настоящее время я поддерживаю код, который это делает, но я не фанат. Я согласен с завершающим подчеркиванием для частных данных, но по какой-то причине мне не нравится префикс m_.

Max Lybbert 22.01.2009 11:23

litb - Я не думаю, что люди называют mangle, потому что у вас не может быть метода и переменной-члена с тем же именем. Таким образом, это не имеет отношения к вопросу. Таким образом, моя точка зрения на то, что ответ является хорошим техническим ответом, пока он не касается проблемы стиля.

jmucchiello 22.01.2009 22:28

@jmu "Я не думаю" - "таким образом, это [искажение имени] не имеет отношения к вопросу". Я не знаю, как ваши личные вопросы (ваше мнение) как-то объективно влияют на уместность чего-либо в моем ответе? я думают, что они (мы!) Действительно искажают из-за проблемы с конфликтами имен, поэтому я помещает это в мой вопрос и считает, что это актуально. Вы еще не представили доказательств своего противоположного утверждения.

Johannes Schaub - litb 24.02.2012 02:17

Мне это не нужно. Я возражаю против того, чтобы конкретный пример mName подразумевался как «обычный». Я не думаю, что вы намереваетесь сказать, что mName - это обычный способ отличить переменные-члены класса от методов класса.

jmucchiello 26.02.2012 05:59

@jmucchiello "Я не думаю, что вы хотите сказать, что mName - это обычный способ отличить переменные членов класса от методов класса". - Я не имел в виду этого. Я сказал: «как бы поставить m перед их именем». «Нравится» означает, что это всего лишь пример, и можно просто написать «_» после имени или еще чего-то. Вы, кажется, обижены тем, что я использую слово «мы». Но под «мы» я подразумеваю многих программистов, включая меня. Что не обязательно включает вас. Не вижу причин для вас обижаться.

Johannes Schaub - litb 17.02.2013 23:45

Я должен согласиться с @jmucchiello. «Обычно мы» настоятельно предполагает, что вы говорите от имени всех, тогда как огромная часть сообщества C++ использует презирает для этого отвратительного соглашения о префиксе m.

Lightness Races in Orbit 05.05.2014 15:08

@LightnessRacesinOrbit Хорошо, я изменю это, так как "мы" имеет то сильное значение, в которое я не поверил, когда писал ответ. Пожалуйста, проверьте, не лучше ли сейчас. Обратите внимание, я не сказал, что «Обычно мы» пишем префикс m. Я сказал, что «мы обычно» специально вызываем данные-члены. Сюда входят все люди, которые используют суффиксы к элементам данных _ и все остальное.

Johannes Schaub - litb 05.05.2014 23:56

Отлично. Стоит ли мне жаловаться на функции получения? :)

jmucchiello 07.05.2014 06:16

Функции в c / C++ - это просто указатели на место в памяти, где расположен код, поэтому isVal (как логическое значение) и isVal (как функция) неоднозначны.

Быстрый ответ: «потому что так работает C++». В C++ нет отдельного пространства имен для переменных-членов и функций-членов (т. Е. «Методов»), в отличие от Java (очевидно, поскольку я этого не пробовал).

В любом случае, вспомните старую историю о парне, который пошел к врачу и сказал: «Док, мне больно, когда я делаю это». На что врач ответил "ну не надо же делать!" Это языковая особенность, которая постепенно превращается в трюк тупого программиста.

Если у вас есть причина использовать одинаковые имена для переменных и методов (возможно, уменьшить именование вещей, которые имеют почти одинаковую цель и т. д.?), Я предлагаю просто назвать их с другим регистром:

class Test 
{
    private bool isVal;
    public bool ISVAL() 
    {   return isVal;  }
}

Я не. Заглушки для функций-членов? Фу.

Lightness Races in Orbit 05.05.2014 15:09

Обычный стиль именования, который я видел в программах на C++, - это называть функции в camelCase, а переменные - в нижнем регистре. На мой взгляд, использование менее известного стиля именования может сбить с толку некоторых читателей.

Zenul_Abidin 24.03.2020 13:05

C++ применяет изменение имен к именам функций и глобальным переменным. Локальные переменные не изменяются. Проблема возникает из-за того, что в C вы можете получить доступ к адресу переменной или функции (в том числе и в C++), например. :

struct noob{
    bool noobvar;
    void noobvar(){};
};

Можно сказать, почему бы не применить изменение имен также и к локальным переменным, а затем иметь внутреннее локальное представление, такое как

bool __noobvar_avar;
void __noobvar_void_fun;

и предположим, что они получают адреса во время выполнения 0x000A и 0x00C0 соответственно.

Однако если мы напишем где-нибудь в коде:

&noob::noobvar

Что должна делать программа?

  1. вернуть адрес переменной noobvar, т.е. 0x000A
  2. вернуть адрес функции noobvar, т.е. 0x00C0

Вы можете видеть, что, поскольку в C и, следовательно, в C++ вы можете выдавать «адрес», недопустимо иметь переменные и функции с одинаковыми именами в одной и той же области разрешения.

В следующем разделе C++ Draft Standard N3337 указывается, когда имя может быть перегружено.

13 Overloading

1 When two or more different declarations are specified for a single name in the same scope, that name is said to be overloaded. By extension, two declarations in the same scope that declare the same name but with different types are called overloaded declarations. Only function and function template declarations can be overloaded; variable and type declarations cannot be overloaded.

Когда вы определяете класс как:

class Test {

      bool isVal() const {
          return isVal;
      }

  private:

      bool isVal;
};

вы перегружаете имя isVal в рамках класса. Такая перегрузка разрешена, только если isVal является функцией-членом. Это не допускается, если isVal является переменной-членом.

Другие вопросы по теме