учебник по Java для С++ говорит, что (выделение - мое):
Конечное ключевое слово примерноэквивалент const в С++
Что означает "грубо" в этом контексте? Разве они не совпадают?
Каковы различия, если они есть?
учебник по Java для С++ говорит, что (выделение - мое):
Конечное ключевое слово примерноэквивалент const в С++
Что означает "грубо" в этом контексте? Разве они не совпадают?
Каковы различия, если они есть?
В С++ обозначение функции-члена const
означает, что она может быть вызвана в экземплярах const
. У Java нет эквивалента этому. Например:.
class Foo {
public:
void bar();
void foo() const;
};
void test(const Foo& i) {
i.foo(); //fine
i.bar(); //error
}
Значения могут быть назначены один раз, позже на Java только, например:
public class Foo {
void bar() {
final int a;
a = 10;
}
}
является законным в Java, но не С++, тогда как:
public class Foo {
void bar() {
final int a;
a = 10;
a = 11; // Not legal, even in Java: a has already been assigned a value.
}
}
В переменных-членах Java и С++ могут быть final
/const
соответственно. Им нужно присвоить значение к моменту завершения экземпляра класса.
В Java они должны быть установлены до завершения конструктора, это может быть достигнуто одним из двух способов:
public class Foo {
private final int a;
private final int b = 11;
public Foo() {
a = 10;
}
}
В С++ вам нужно будет использовать списки инициализации, чтобы дать const
members значение:
class Foo {
const int a;
public:
Foo() : a(10) {
// Assignment here with = would not be legal
}
};
В финале Java можно использовать для обозначения вещей как незащищенных. С++ (pre-С++ 11) этого не делает. Например:.
public class Bar {
public final void foo() {
}
}
public class Error extends Bar {
// Error in java, can't override
public void foo() {
}
}
Но в С++:
class Bar {
public:
virtual void foo() const {
}
};
class Error: public Bar {
public:
// Fine in C++
virtual void foo() const {
}
};
это прекрасно, потому что семантика маркировки функции-члена const
различна. (Вы также можете перегрузить, только имея const
в одной из функций-членов. (Обратите также внимание на то, что С++ 11 позволяет отмечать окончательные элементы-члены, см. Раздел обновления С++ 11)
С++ 11 действительно позволяет вам отмечать как классы, так и функции-члены как final
, с одинаковой семантикой для одной и той же функции в Java, например, в Java:
public class Bar {
public final void foo() {
}
}
public class Error extends Bar {
// Error in java, can't override
public void foo() {
}
}
Теперь можно точно написать на С++ 11 как:
class Bar {
public:
virtual void foo() final;
};
class Error : public Bar {
public:
virtual void foo() final;
};
Мне пришлось скомпилировать этот пример с предварительным выпуском g++ 4.7. Обратите внимание, что в этом случае это не заменяет const
, а дополняет его, обеспечивая поведение, подобное Java, которое не было замечено с ближайшим эквивалентным ключевым словом С++. Поэтому, если вы хотите, чтобы функция-член была как final
, так и const
, вы должны:
class Bar {
public:
virtual void foo() const final;
};
(Здесь требуется порядок const
и final
).
Раньше не было прямого эквивалента функций-членов const
, хотя функции non virtual
были бы потенциальным вариантом, хотя бы не вызывая ошибки во время компиляции.
Аналогично Java:
public final class Bar {
}
public class Error extends Bar {
}
переходит в С++ 11:
class Bar final {
};
class Error : public Bar {
};
(Раньше конструкторы private
были, вероятно, ближе всего к С++)
Интересно, что для поддержания обратной совместимости с pre-С++ 11 код final
не является ключевым словом обычным способом. (Возьмите тривиальный, законный пример С++ 98 struct final;
, чтобы понять, почему его ключевое слово сломало бы код)
В Java ключевое слово final может использоваться для четырех вещей:
Одна важная вещь: Конечная переменная участника Java должна задаваться ровно один раз! Например, в конструкторе, декларации поля или intializer. (Но вы не можете установить конечную переменную-член в методе).
Еще одно следствие создания переменной-члена-члена относится к модели памяти, что важно, если вы работаете в потоковой среде.
Объект A const
может вызывать только методы const
и обычно считается неизменным.
const Person* person = myself;
person = otherPerson; //Valid... unless we declared it const Person* const!
person->setAge(20); //Invalid, assuming setAge isn't a const method (it shouldn't be)
Объект A final
не может быть установлен на новый объект, но он не является неизменным - нет ничего, что помешало бы кому-либо вызвать какие-либо методы set
.
final Person person = myself;
person = otherPerson; //Invalid
person.setAge(20); //Valid!
Java не имеет неотъемлемого способа объявления объектов неизменяемыми; вам нужно создать класс как непреложный.
Когда переменная является примитивным типом, final
/const
работают одинаково.
const int a = 10; //C++
final int a = 10; //Java
a = 11; //Invalid in both languages
Java final эквивалентен С++ const в примитивных типах значений.
С ссылочными типами Java ключевое слово final эквивалентно указателю const... i.e.
//java
final int finalInt = 5;
final MyObject finalReference = new MyObject();
//C++
const int constInt = 5;
MyObject * const constPointer = new MyObject();
Здесь у вас есть отличные ответы, но один момент, который, кажется, стоит добавить: const
в С++ обычно используется, чтобы другие части программы не изменяли состояние объектов. Как было указано, final
в java не может этого сделать (кроме примитивов) - он просто запрещает замену ссылки на другой объект. Но если вы используете Collection
, вы можете предотвратить изменения в своих объектах, используя статический метод
Collection.unmodifiableCollection( myCollection )
Это возвращает ссылку Collection
, которая дает доступ к чтению элементам, но генерирует исключение, если попытки изменения выполняются, что немного напоминает const
в С++
Java final
работает только с примитивными типами и ссылками, но не с самими экземплярами объектов, где ключевое слово const работает с чем угодно.
Сравните const list<int> melist;
с final List<Integer> melist;
первый делает невозможным изменение списка, в то время как последний только мешает вам назначить новый список для melist
.
Помимо наличия определенных и тонких многопоточных свойств, объявленные переменные final
не должны быть инициализированы в объявлении!
то есть. Это действительно в Java:
// declare the variable
final int foo;
{
// do something...
// and then initialize the variable
foo = ...;
}
Это недействительно, если написано с С++ const
.
Согласно wikipedia:
Я предполагаю, что он говорит "грубо", потому что значение const
в С++ усложняется, когда вы говорите о указателях, то есть указатели констант против указателей на постоянные объекты. Поскольку в Java нет "явных" указателей, final
не имеет этих проблем.
Позвольте мне объяснить, что я понял с примером оператора switch/case.
Значения в каждом случае должны быть постоянными значениями времени компиляции того же типа данных, что и значение переключателя.
объявить что-то вроде ниже (либо в вашем методе как локальные экземпляры, либо в вашем классе как статическую переменную (добавьте в нее статическую информацию) или переменную экземпляра.
final String color1 = "Red";
и
static final String color2 = "Green";
switch (myColor) { // myColor is of data type String
case color1:
//do something here with Red
break;
case color2:
//do something with Green
break;
}
Этот код не будет компилироваться, если color1
- это переменная класса/экземпляра, а не локальная переменная.
Это будет скомпилировано, если color1
определяется как статическое окончательное (тогда оно становится статической конечной переменной).
Когда он не компилируется, вы получите следующую ошибку:
error: constant string expression required
ключевое слово "const" означает, что ваша переменная сохраняется в ПЗУ (с микропроцессором). в компьютере ваша переменная сохраняется в области ОЗУ для кода сборки (только для ОЗУ). это означает, что ваша переменная не входит в записываемое ОЗУ: статическая память, память стека и память кучи.
ключевое слово "final" означает, что ваша переменная сохраняется в записываемой ОЗУ, но вы замечаете компилятору, что ваша переменная изменяется только один раз.
//in java language you can use:
static final int i =10;
i =11; //error is showed here by compiler
//the same in C++ the same as follows
int i =10;
const int &iFinal = i;
iFinal = 11; //error is showed here by compiler the same as above
Я думаю, что "const" плохо работает, поэтому Java не использует его.