Метод класса и переменная с тем же именем, ошибка компиляции в С++ не в 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?
Ответы
Ответ 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; }
}