Окончание Java против С++ const

учебник по Java для С++ говорит, что (выделение - мое):

Конечное ключевое слово примерноэквивалент const в С++

Что означает "грубо" в этом контексте? Разве они не совпадают?

Каковы различия, если они есть?

Ответ 1

В С++ обозначение функции-члена 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:

С++ 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;, чтобы понять, почему его ключевое слово сломало бы код)

Ответ 2

В Java ключевое слово final может использоваться для четырех вещей:

  • для класса или метода для его герметизации (не разрешено подклассы/переопределение)
  • в переменной-члене, чтобы объявить, что она может быть установлена ​​ровно один раз (я думаю, это то, о чем вы говорите)
  • для переменной, объявленной в методе, чтобы убедиться, что ее можно установить ровно один раз
  • в параметре метода, чтобы объявить, что он не может быть изменен в рамках метода

Одна важная вещь: Конечная переменная участника Java должна задаваться ровно один раз! Например, в конструкторе, декларации поля или intializer. (Но вы не можете установить конечную переменную-член в методе).

Еще одно следствие создания переменной-члена-члена относится к модели памяти, что важно, если вы работаете в потоковой среде.

Ответ 3

Объект 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

Ответ 4

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();

Ответ 5

Здесь у вас есть отличные ответы, но один момент, который, кажется, стоит добавить: const в С++ обычно используется, чтобы другие части программы не изменяли состояние объектов. Как было указано, final в java не может этого сделать (кроме примитивов) - он просто запрещает замену ссылки на другой объект. Но если вы используете Collection, вы можете предотвратить изменения в своих объектах, используя статический метод

 Collection.unmodifiableCollection( myCollection ) 

Это возвращает ссылку Collection, которая дает доступ к чтению элементам, но генерирует исключение, если попытки изменения выполняются, что немного напоминает const в С++

Ответ 6

Java final работает только с примитивными типами и ссылками, но не с самими экземплярами объектов, где ключевое слово const работает с чем угодно.

Сравните const list<int> melist; с final List<Integer> melist; первый делает невозможным изменение списка, в то время как последний только мешает вам назначить новый список для melist.

Ответ 7

Помимо наличия определенных и тонких многопоточных свойств, объявленные переменные final не должны быть инициализированы в объявлении!

то есть. Это действительно в Java:

// declare the variable
final int foo;

{
    // do something...

    // and then initialize the variable
    foo = ...;
}

Это недействительно, если написано с С++ const.

Ответ 8

Согласно wikipedia:

  • В С++ поле const не только защищено от переназначения, но есть дополнительное ограничение, которое на него могут вызывать только методы const, и оно может передаваться только как аргумент const других методов.
  • Нестатические внутренние классы могут свободно обращаться к любому полю охватывающего класса, окончательному или нет.

Ответ 9

Я предполагаю, что он говорит "грубо", потому что значение const в С++ усложняется, когда вы говорите о указателях, то есть указатели констант против указателей на постоянные объекты. Поскольку в Java нет "явных" указателей, final не имеет этих проблем.

Ответ 10

Позвольте мне объяснить, что я понял с примером оператора 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

Ответ 11

ключевое слово "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 не использует его.