Tips Học Nhanh Khi Chuyển Từ Java Sang C++
C ++ là ngôn ngữ lập trình nhanh, mạnh mẽ và linh hoạt. Trong bài viết, hãy cùng mình tìm hiểu một số mẹo để có thể chuyển từ lập trình viên Java sang C++ một cách nhanh chóng.
Bài viết này là cần thiết cho các bạn sinh viên có nền tảng Java và muốn học C++ để tham gia các buổi học trên lớp. Đương nhiên là nếu việc học các môn đều dựa trên Java sẽ dễ hơn, nhưng học cách chuyển đổi từ ngôn ngữ này sang ngôn ngữ khác là một thực tế cuộc sống của các chuyên gia phát triển phần mềm hiện nay. Cùng bắt đầu thôi!
1. Kiểu dữ liệu và biến
Các kiểu dữ liệu trong C++ cũng tương tự trong Java. Giống như Java, C ++ có kiểu int và double.
C ++ có kiểu dữ liệu short và unsigned có thể lưu trữ số hiệu quả hơn. Tốt nhất là tránh các loại này trừ khi hiệu quả tăng thêm là rất quan trọng.
Kiểu Boolean được gọi là bool trong C ++.
Kiểu chuỗi C ++ được gọi là string. Nó khá giống với kiểu String trong Java . Tuy nhiên, hãy chú ý đến những khác biệt này:
1. Chuỗi C ++ lưu trữ các ký tự ASCII, không phải các ký tự Unicode
2. Chuỗi C ++ có thể được sửa đổi, trong khi chuỗi Java là bất biến.
3. Các hoạt động substring trong C ++ có thể sử dụng hàm substr. Lệnh s.substr(i, n) trích xuất một chuỗi con có độ dài n bắt đầu từ vị trí i .
4. Bạn chỉ có thể nối các chuỗi với các chuỗi khác, không phải với các đối tượng tùy ý.
5. Để so sánh các chuỗi, sử dụng các toán tử quan hệ == != < <= > >= . Bốn toán tử cuối cùng thực hiện so sánh từ điển. Đây thực sự là điều thuận tiện hơn so với việc sử dụng equals và compareTo trong Java.
2. Các từ khóa mới
Trong Java, các objects được khởi tạo bởi keyword new. Do đó, một cách tự nhiên khi cho rằng có thể sử dụng new trong C++ một cách tương tự
// Java
int f() {
Foo foo = new Foo();
return foo.bar();
}
// C++
int f() {
Foo* foo = new Foo();
return foo->bar(); // Leak!
}
Tuy nhiên, không giống với Java, biến trong C++ khởi tạo bởi new là không được quản lý. Do đó bạn nên nhớ giải phóng bộ nhớ cho biến sau khi sử dụng.
int f() {
Foo* foo = new Foo();
int x = foo->bar();
delete foo; // How inconvenient!
return x;
}
Điều này có thể thực hiện bởi keyword delete. Khi từ Java chuyển sang C++, điều này có vẻ bất tiện và rất dễ bị lỗi. Tại sao một câu lệnh trong Java rất dễ nhưng trong C++ lại cần phải bổ sung thêm câu lệnh?
Trong C++ có rất nhiều cách để khởi tạo một đối tượng. Và cách dễ nhất là khởi tạo trực tiếp lên callstack
int f() {
Foo foo;
return foo.bar(); // foo automatically destroyed
}
Khi các biến được gọi vào callstack, chúng sẽ tự động bị xóa ngay sau khi được sử dụng xong. Đoạn code trở nên ngắn gọn hơn và có hiệu suất tuyệt vời.
3. const của C++ mạnh mẽ hơn final của Java
Một điều phổ biến khi thiết kế các chương trình lớn là tạo ra các hằng số không thay đổi trong cả chương trình.
Trong Java sử dụng từ khóa final để tham chiếu một biến là hằng. Tuy nhiên dữ liệu vẫn có thể bị thay đổi. Ví dụ:
final List<String> xs = new ArrayList<>();
// We can modify xs internally
xs.add("a");
xs.add("b");
xs.add("c");
// ... but we cannot change where it points to!
xs = new ArrayList<>(); // Will not compile
Vì vậy, để tạo các loại thực sự bất biến, các nhà phát triển Java phải đánh dấu tất cả các trường bên trong một class là final:
public final class Person {
public final String firstName;
public final String lastName;
public Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
final Person person = new Person("John", "Smith");
person.firstName = "Bob"; // Will not compile!
Trong C++, có từ khóa const mạnh hơn nhiều. Một khi biến đã được khai báo là const thì sẽ không thể thay đổi được trong toàn bộ chương trình. Ngay cả khi chúng không được khai báo trong class
struct Person {
std::string firstName; // No need for const here!
std::string lastName;
};
Person const person = { "John", "Smith" };
person.firstName = "Bob"; // Will not compile!
4. Nạp chồng toán tử
Java không cho phép bạn định nghĩa một kiểu dữ liệu và phép toán của nó đơn giản như int, boolean. Ví dụ như trong class dưới đây có thể thấy việc thực thi phép tính bằng vector và ma trận khá cồng kềnh
public final class Vector2 {
public final float x;
public final float y;
public Vector2(float x, float y) {
this.x = x;
this.y = y;
}
public Vector2 add(final Vector2 v) {
return new Vector2(x + v.x, y + v.y);
}
// toString, hashCode, equals…
}
Vector2 v = new Vector2(1, 2);
Vector2 u = new Vector2(3, 4);
Vector2 w = v.add(w);
Trong C++, chúng ta chỉ cần đơn giản là nạp chồng toán tử như sau:
struct Vector2 {
float x;
float y;
};
inline Vector2 operator+(Vector2 const& lhs, Vector2 const& rhs) {
return { lhs.x + rhs.x, lhs.y + lhs.y };
}
Đoạn code trên giúp chúng ra có thể cộng trong class vector một cách đơn giản như sau
Vector2 v = { 1, 2 };
Vector2 u = { 3, 4 };
Vector2 w = v + w; // Much better!
5. Hàm
Trong Java, mọi hàm phải là một method hoặc static function của một class. C++ cũng hỗ trợ method và static function của một class giống như Java, nhưng nó cũng đồng thời cho phép việc viét và sử dụng hàm không thuộc về một class nào, những hàm này được gọi là hàm cục bộ (global functions).
Đặc biệt, mọi hàm C++ bắt đầu bởi hàm main.
int main() {
// Do somethings
}
Trong Java, việc xử lý hàm chỉ có thể sử dụng được truyền tham trị, trong C++ còn hỗ trợ việc truyền tham chiếu, có thể tham khảo ở bài viết này
6. Input/Output
Trong C++, luồng đầu vào và đầu ra tiêu chuẩn được thể hiện bằng đối tượng cin và cout (cần include thư viện cần thiết và sử dụng namespace std).
Bạn sử dụng cout và toán tử << để viết đầu ra.
int ans = 1;
cout << "Answer is: " << ans << "\n";
Để đọc đầu vào, bạn sử dụng cin và toán tử >> .
double x;
long y;
string z;
cin >> x >> y >> z;
Khi đọc một xâu không có khoảng trống, bạn có thể sử dụng cin như trên, nhưng nếu muốn đọc cả một dòng bao gồm cả khoảng trống thì dùng getline như dưới đây
string s;
getline(cin, s);
7. Con trỏ
Trong Java có cơ chế thu hồi bộ nhớ nếu như biến không được sử dụng nhưng trong C/C++ thì không như vậy, mọi việc đều phải do lập trình viên phải tự làm hết, do đó con trỏ được sinh ra để giúp cho việc cấp phát động bộ nhớ và sử dụng. Việc cấp phát động được coi là một phương pháp để lập trình viên có thể quản lý bộ nhớ một cách chủ động và có thể dọn dẹp dễ hơn cấp phát tĩnh. Đây cũng là một vấn đề cần quan tâm khi chuyển từ Java sang C++.
Tạm kết
Qua bài viết mình đã giới thiệu sơ lược một vài thứ cần biết khi mới chuyển từ Java sang C++. Trong khuôn khổ bài viết giới thiệu, chắc chắn không thể đi sâu được từng vấn đề. Trong tương lai nếu có dịp mình sẽ giới thiệu chi tiết hơn về từng vấn đề trong bài viết. Chúc các bạn thành công.
References:
- horstmann.com
- hackernoon.com