В маркировке C ++ функция-член const
означает, что она может вызываться в const
экземплярах. У Java нет эквивалента этому. E.g.:
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 final может использоваться для пометки вещей как не подлежащих переопределению. C ++ (до C ++ 11) этого не делает. E.g.:
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 обновление:
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
функций-членов, хотя создание функций, не являющихся 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;
, чтобы понять, почему его использование в качестве ключевого слова может нарушить код)