Trong C ++, đánh dấu một hàm thành viên const
có nghĩa là nó có thể được gọi trong các const
trường hợp. Java không có tương đương với điều này. Ví dụ:
class Foo {
public:
void bar();
void foo() const;
};
void test(const Foo& i) {
i.foo(); //fine
i.bar(); //error
}
Các giá trị có thể được chỉ định, một lần, sau này chỉ trong Java, vd:
public class Foo {
void bar() {
final int a;
a = 10;
}
}
là hợp pháp trong Java, nhưng không phải C ++ trong khi:
public class Foo {
void bar() {
final int a;
a = 10;
a = 11; // Not legal, even in Java: a has already been assigned a value.
}
}
Trong cả hai biến thành viên Java và C ++ có thể là final
/ const
tương ứng. Chúng cần được cung cấp một giá trị tại thời điểm một thể hiện của lớp được hoàn thành.
Trong Java, chúng phải được đặt trước khi hàm tạo kết thúc, điều này có thể đạt được theo một trong hai cách:
public class Foo {
private final int a;
private final int b = 11;
public Foo() {
a = 10;
}
}
Trong C ++, bạn sẽ cần sử dụng các danh sách khởi tạo để cung cấp cho const
các thành viên một giá trị:
class Foo {
const int a;
public:
Foo() : a(10) {
// Assignment here with = would not be legal
}
};
Trong Java cuối cùng có thể được sử dụng để đánh dấu những thứ là không thể ghi đè. C ++ (tiền C ++ 11) không làm điều này. Ví dụ:
public class Bar {
public final void foo() {
}
}
public class Error extends Bar {
// Error in java, can't override
public void foo() {
}
}
Nhưng trong C ++:
class Bar {
public:
virtual void foo() const {
}
};
class Error: public Bar {
public:
// Fine in C++
virtual void foo() const {
}
};
Điều này là tốt, bởi vì ngữ nghĩa của việc đánh dấu một chức năng thành viên const
là khác nhau. (Bạn cũng có thể quá tải khi chỉ có const
một trong các chức năng thành viên. (Cũng lưu ý rằng C ++ 11 cho phép các chức năng thành viên được đánh dấu cuối cùng, xem phần cập nhật C ++ 11)
Cập nhật C ++ 11:
C ++ 11 trên thực tế cho phép bạn đánh dấu cả hai lớp và các hàm thành viên là final
, với ngữ nghĩa giống hệt nhau cho cùng một tính năng trong Java, ví dụ như trong Java:
public class Bar {
public final void foo() {
}
}
public class Error extends Bar {
// Error in java, can't override
public void foo() {
}
}
Bây giờ có thể được viết chính xác trong C ++ 11 như:
class Bar {
public:
virtual void foo() final;
};
class Error : public Bar {
public:
virtual void foo() final;
};
Tôi đã phải biên dịch ví dụ này với bản phát hành trước G ++ 4.7. Lưu ý rằng điều này không thay thế const
trong trường hợp này, mà là tăng cường nó, cung cấp hành vi giống như Java không thấy với từ khóa C ++ tương đương gần nhất. Vì vậy, nếu bạn muốn một hàm thành viên là cả hai final
và const
bạn sẽ làm:
class Bar {
public:
virtual void foo() const final;
};
(Thứ tự const
và final
ở đây là bắt buộc).
Trước đây không có sự tương đương trực tiếp của các const
hàm thành viên mặc dù việc tạo các hàm không virtual
phải là một tùy chọn tiềm năng mặc dù không gây ra lỗi khi biên dịch.
Tương tự như vậy Java:
public final class Bar {
}
public class Error extends Bar {
}
trở thành C ++ 11:
class Bar final {
};
class Error : public Bar {
};
(Các nhà private
xây dựng trước đây có lẽ là người gần nhất bạn có thể nhận được điều này trong C ++)
Thật thú vị, để duy trì khả năng tương thích ngược với mã trước C ++ 11 final
không phải là một từ khóa theo cách thông thường. (Lấy ví dụ C ++ 98 tầm thường, hợp pháp struct final;
để xem tại sao làm cho nó trở thành một từ khóa sẽ phá vỡ mã)