У 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 ++ (pre-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 дозволяє функції члена відзначати остаточними, див. Розділ оновлення 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 ++)
Цікаво, що для підтримки зворотної сумісності з кодом pre-C ++ 11 final
це не ключове слово звичайним чином. (Візьміть тривіальний, легальний приклад C ++ 98, struct final;
щоб дізнатися, чому створення ключового слова порушить код)