Подтвердить что ты не робот

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

class Test {

      bool isVal() const {
          return isVal;
      }

  private:

      bool isVal;
};

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

testClass.cpp: 9: объявление 'bool Test :: isVal'

testClass.cpp: 3: конфликтует с предыдущим объявлением 'bool Test :: isVal()'

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

class Test {

  private boolean isVal;

  public boolean isVal() {
      return isVal;
  }

}

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

4b9b3361

Ответ 1

Потому что С++ - это не Java. Вы можете принять адрес члена:

&Test::isVal

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

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

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

Ответ 2

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

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

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

bool __noobvar_avar;
void __noobvar_void_fun;

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

Однако, если мы пишем где-то в коде:

&noob::noobvar

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

  • возвращает адрес переменной noobvar, т.е. 0x000A
  • возвращает addres функции noobvar, т.е. 0x00C0

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

Ответ 3

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

Ответ 4

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

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

Ответ 5

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

13 Перегрузка

1 Если для одного имени в одной и той же области указаны два или более разных объявления, это имя считается перегруженным. По расширению два объявления в той же области, которые объявляют одно и то же имя, но с разными типами, называются перегруженными объявлениями. Только объявления шаблонов функций и функций могут быть перегружены; объявления переменных и типов не могут быть перегружены.

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

class Test {

      bool isVal() const {
          return isVal;
      }

  private:

      bool isVal;
};

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

Ответ 6

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

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