В учебнике по программированию на Java для C ++ говорится, что (выделение - мое):
Ключевое слово final примерно эквивалентно const в C ++
Что значит «грубо» в этом контексте? Разве они точно так же?
Каковы различия, если таковые имеются?
В учебнике по программированию на Java для C ++ говорится, что (выделение - мое):
Ключевое слово final примерно эквивалентно const в C ++
Что значит «грубо» в этом контексте? Разве они точно так же?
Каковы различия, если таковые имеются?
Ответы:
В C ++ маркировка членской функции 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, но не в C ++, тогда как:
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, и в C ++ переменные-члены могут быть final
/ const
соответственно. Им должно быть присвоено значение к моменту завершения создания экземпляра класса.
В Java они должны быть установлены до завершения конструктора, это может быть достигнуто одним из двух способов:
public class Foo {
private final int a;
private final int b = 11;
public Foo() {
a = 10;
}
}
В C ++ вам нужно будет использовать списки инициализации, чтобы дать const
членам значение:
class Foo {
const int a;
public:
Foo() : a(10) {
// Assignment here with = would not be legal
}
};
В Java финал может использоваться, чтобы пометить вещи как не подлежащие переопределению. C ++ (до C ++ 11) этого не делает. Например:
public class Bar {
public final void foo() {
}
}
public class Error extends Bar {
// Error in java, can't override
public void foo() {
}
}
Но в C ++:
class Bar {
public:
virtual void foo() const {
}
};
class Error: public Bar {
public:
// Fine in C++
virtual void foo() const {
}
};
это хорошо, потому что семантика маркировки функции-члена const
различна. (Вы также можете перегрузить , только включив const
одну из функций-членов. (Обратите внимание также, что C ++ 11 позволяет функциям-членам быть помеченными как final, см. Раздел обновления C ++ 11)
C ++ 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() {
}
}
Теперь можно точно написать на C ++ 11 как:
class Bar {
public:
virtual void foo() final;
};
class Error : public Bar {
public:
virtual void foo() final;
};
Мне пришлось скомпилировать этот пример с предварительной версией G ++ 4.7. Обратите внимание, что это не заменяет const
в этом случае, а скорее дополняет его, предоставляя Java-подобное поведение, которое не было видно с наиболее близким эквивалентным ключевым словом C ++. Поэтому, если вы хотите, чтобы функция-член была и тем, 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 {
}
делается в C ++ 11:
class Bar final {
};
class Error : public Bar {
};
(Ранее private
конструкторы были, вероятно, ближе всего к этому в C ++)
Интересно, что для обеспечения обратной совместимости с кодом до C ++ 11 final
это не ключевое слово обычным способом. (Возьмем тривиальный, легальный пример C ++ 98, struct final;
чтобы понять, почему создание ключевого слова может привести к поломке кода)
final int a; a = 10; a = 11;
это не так (это является целью final
модификатора переменной). Кроме того, конечные члены класса могут быть установлены только во время объявления или один раз в конструкторе. ,
final
декоратор-член для этой конкретной цели. VC ++ 2005, 2008 и 2010 уже реализовали это, используя sealed
вместо этого контекстное ключевое слово final
.
В Java последнее ключевое слово может использоваться для четырех вещей:
Одна важная вещь: переменная конечного члена Java должна быть установлена ровно один раз! Например, в конструкторе, объявлении поля или инициализаторе. (Но вы не можете установить конечную переменную-член в методе).
Другое последствие создания переменной-члена final относится к модели памяти, что важно, если вы работаете в многопоточной среде.
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)
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 эквивалентен C ++ const для типов примитивных значений.
В ссылочных типах Java последнее ключевое слово эквивалентно константному указателю ... т.е.
//java
final int finalInt = 5;
final MyObject finalReference = new MyObject();
//C++
const int constInt = 5;
MyObject * const constPointer = new MyObject();
У вас уже есть несколько хороших ответов, но один момент, который, кажется, стоит добавить: const
в C ++ обычно используется для предотвращения изменения состояния других частей программы. Как уже указывалось, final
в Java это не может быть сделано (за исключением примитивов) - оно просто предотвращает изменение ссылки на другой объект. Но если вы используете Collection
, вы можете предотвратить изменения ваших объектов с помощью статического метода
Collection.unmodifiableCollection( myCollection )
Это возвращает Collection
ссылку, которая дает доступ на чтение к элементам, но выдает исключение, если попытки изменения сделаны, делая это немного как const
в C ++
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 = ...;
}
Это не будет действительным, если написано с C ++ const
.
Согласно википедии :
Позвольте мне объяснить, что я понял, на примере оператора switch / case.
Значения в каждом операторе 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
определено как static final (тогда оно становится статической final final).
Когда он не скомпилируется, вы получите следующую ошибку
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 его не использует.