Đề tài Điểm giống và khác nhau giữa C++, C# và Java
Trong C++ có hai cách để chú thích:
// Chú thích theo dòng
/* Chú thích theo khối */
Chú thích theo dòng bắt đầu từ cặp dấu sổ (//) cho đến cuối dòng. Chú thích
theo khối bắt đầu bằng /* và kết thúc bằng */ và có thể bao gồm nhiều dòng.
Trong C# có ba cách chú thích: trong đó có hai cách giống như C++.
Cách thử là chú thích xml, ghi chép tài liệu của 1 lớp hoạc phương thức
sử dụng một phần xml. Ngoài ra, nó còn tạo tài liệu API cho ứng dụng.
sử dụng biến không đúng kiểu. C#: kiểm tra kiểu của một đối tượng. » Sử dụng phương thức thừa kế Object.GetType để thu lấy Type cho đối tượng này. Trong vài trường hợp, bạn cũng có thể sử dụng toán tử is và as để kiểm tra kiểu của một đối tượng. Tất cả các kiểu dữ liệu đều thừa kế phương thức GetType từ lớp cơ sở Object. Phương thức này trả về một tham chiếu Type mô tả kiểu của đối tượng. Bộ thực thi duy trì một đối tượng Type cho mỗi kiểu được nạp và tất cả các tham chiếu cho kiểu này cùng chỉ đến đối tượng này. Điều này nghĩa là bạn có thể so sánh hai tham chiếu kiểu một cách hiệu quả. Ví dụ dưới đây trình bày cách kiểm tra một đối tượng có phải là System.IO.StringReader hay không: // Tạo một StringReader để thử nghiệm. Object someObject = new StringReader("This is a StringReader"); // Kiểm tra xem someObject có phải là một StringReader hay không // bằng cách thu lấy và so sánh tham chiếu Type (sử dụng toán tử typeof). if (typeof(System.IO.StringReader) == someObject.GetType()) { // Làm gì đó. § } C# cung cấp toán tử is để thực hiện nhanh việc kiểm tra như trên. Ngoài ra, is sẽ trả về true nếu đối tượng cần kiểm tra dẫn xuất từ lớp được chỉ định. Đoạn mã dưới đây kiểm tra xem someObject là một thể hiện của System.IO.TextReader, hay một lớp dẫn xuất từ TextReader (như StringReader): // Kiểm tra xem someObject là TextReader, // hay dẫn xuất từ TextReader bằng toán tử is. if (someObject is System.IO.TextReader) { // Làm gì đó. § } Cả hai cách này đều đòi hỏi kiểu dùng với toán tử typeof và is phải là kiểu đã biết và khả phân giải lúc biên dịch. Một cách khác linh hoạt hơn (nhưng chậm hơn) là sử dụng phương thức Type.GetType để trả về một tham chiếu Type cho kiểu được chỉ định. Tham chiếu Type không được phân giải cho đến khi thực thi, việc này ảnh hưởng đến hiệu năng, nhưng cho phép bạn thay đổi phép so sánh kiểu lúc thực thi dựa trên giá trị của một chuỗi. Phương thức IsType dưới đây sẽ trả về true nếu đối tượng thuộc kiểu được chỉ định và sử dụng phương thức Type.IsSubclassOf để kiểm tra đối tượng này có phải là một lớp con của kiểu được chỉ định hay không. public static bool IsType(object obj, string type) { Type t = Type.GetType(type, true, true); return t == obj.GetType() || obj.GetType().IsSubclassOf(t); } Cuối cùng, bạn có thể sử dụng toán tử as để ép bất kỳ đối tượng nào sang kiểu được chỉ định. Nếu đối tượng không thể bị ép sang kiểu được chỉ định, toán tử as sẽ trả về null. Điều này cho phép bạn thực hiện các phép ép kiểu an toàn (safe cast), nhưng kiểu được so sánh phải là khả phân giải lúc thực thi. Dưới đây là một ví dụ: // Sử dụng toán tử as để thực hiện một phép ép kiểu an toàn. StringReader reader = someObject as System.IO.StringReader; if (reader != null) { // Làm gì đó. § } Sự ép kiểu cũng được hỗ trợ tốt hơn trong Java, quá trình tự động ép kiểu chỉ xảy ra khi không bị mất đi những tính chất của chương trình. Tất cả các phép ép kiểu khác là không hàon chỉnh. Các kiểu dữ liệu cơ bản như int, float, long, char, boolean… không thể bị ép vào các đối tượng được. Trong java có các phương thức và đặc biệt là lớp” Wraper” dùng để chuyển qua lại giữa các đối tượng và kiểu dữ liệu cơ bản. Trong quá trình kiểm tra kiểu, nếu có sự không tương thích giữa kiểu thực của đối số và kiểu đang được monng đợi của phép toán ấy thì có hai lựa chọn có thể: Sự không tương thích kiểu bị báo lỗi hoặc Một sự chuyển đổi kiểu tự động được thi hành để đổi kiểu của đối số thực tế thành kiểu đúng với yêu cầu. Chuyển đổi kiểu: là một phép toán được định nghĩa như sau: Sự chuyển đổi: Kiểu1 -> Kiểu2 nghĩa là sự chuyển đổi lấy ÐTDL của một kiểu và sản sinh ra một ÐTDL "tương ứng" của một kiểu khác. Hầu hết các ngôn ngữ đều cung cấp hai phương pháp chuyển đổi kiểu: Trang bị một tập hợp các hàm đã được xây dựng mà người lập trình có thể gọi trong chương trình để tạo ra sự chuyển đổi kiểu. Ví dụ Pascal trang bị hàm ROUND để đổi một ÐTDL số thực thành một đối tượng dữ liệu nguyên với giá trị bằng phần nguyên của số thực. Như là một sự chuyển đổi tự động (còn gọi là ép kiểu) do ngôn ngữ thực hiện trong một số trường hợp không tương thích kiểu nào đó. Ví dụ trong Pascal các đối số của phép toán số học "+" có lẫn số thực và số nguyên hoặc khi gán một số nguyên cho một biến số thực thì số nguyên phải được đổi một cách tự động thành kiểu thực. Ðối với kiểm tra kiểu động thì sự chuyển đổi kiểu tự động được diễn ra tại điểm mà sự không tương thích kiểu được tìm thấy trong quá trình thực hiện chương trình. Ðối với sự kiểm tra kiểu tĩnh thì một mã phụ sẽ được xen vào trong chương trình đích dùng để gọi tới hàm biến đổi kiểu tại điểm thích hợp trong quá trình thực hiện. Chuyển đổi kiểu tự động giúp người lập trình khỏi mọi lo lắng về sự sai kiểu và tránh việc gọi tới một số lượng lớn các phép biến đổi kiểu tường minh trong chương trình. Tuy nhiên chúng ta nên tránh việc chuyển đổi kiểu bằng cách viết các phép toán đúng kiểu. Chẳng hạn trong lập trình thay vì viết lệnh x := 1 (với x là biến số thực) ta nên viết x := 1.0, với lệnh trước thì khi thực hiện phải có một sự chuyển đổi kiểu tự động còn với lệnh sau thì không cần nên thời gian thực hiện sẽ nhanh hơn. 5.Namespace: Namespaces cho phép chúng ta gộp một nhóm các lớp, các đối tượng toàn cục và các hàm dưới một cái tên. Nói một cách cụ thể hơn, chúng dùng để chia phạm vi toàn cụ thành những phạm vi nhỏ hơn với tên gọi namespaces. namespace chỉ đơn giản là phân biệt method của lớp này với method của lớp khác mà chúng có cùng tên. VD: 2 nhà ỏ gần nhau. Có 2 người con cùng là Tuấn. Thì lúc chúng ta gọi Tuấn thì không biết Tuấn nào. Vậy chúng ta phải gọi Tuấn của ông A hay Tuấn của ông B. Thì namespace nó cũng tương tự như vậy. Trong 2 lớp có cùng tên hành vi. Khi chúng ta gọi hành vi đó thì hành vi đó là của namespace nào. Namespace đơn giản là như thế. C++: Khuông mẫu để sử dụng namespaces là: namespace identifier { namespace-body } C#: System.Console.WriteLine(); Java: trong java không có namespace chỉ dùng packet. 6.Quản lý bộ nhớ và cấp phát bộ nhớ: Khi mới lập trình, thì nếu không nắm rõ về bộ nhớ chung ta sẽ gặp một số rắc rối như: Lãng phí bộ nhớ: giả sử bạn khai báo int array_entry[100] thì bạn sẽ có 1 vùng nhớ cho 100 phần tử, nhưng nếu chương trình của bạn chỉ thường xuyên dùng có 10 phần tử, và 1 vài lần là dùng đến 100 phần tử thì tức là bạn đã phí phạm 90 phần tử. Thiếu bộ nhớ: vì tiết kiệm, bạn chỉ khai báo int array_entry[10], nhưng nếu bạn cần dùng đến 15 phần tử thì...overflow ngay. Chưa hết, array cần một vùng nhớ liên tục, giả sử máy bạn vẫn còn nhiều bộ nhớ trống, nhưng không có vùng nhớ trống liên tục nào đủ lớn cho mảng của bạn. Thế là vẫn...thiếu bộ nhớ. Để giải quyết việc này người ta dùng phương pháp cấp phát bộ nhớ động. C++: có thể dùng malloc (để cấp phát bộ nhớ) và hàm free(giải phóng bộ nhớ cấp phát). C++: dùng new (để cấp phát )và delete(để giải phóng bộ nhớ cấp phát). C#:dùng new (để cấp phát), và không cần phải delete. Vì trong C# có cơ chế don rác tự động. Riêng java không có kiểu dữ liệu con trỏ như trong C++, người lập trình không cần phải quá bận tâm về việc cấp phát và giải phóng vùng nhớ, sẽ có một trình dọn dẹp hệ thống đảm trách việc này. Trình dọn dẹp hệ thống sẽ dọn dẹp vùng nhớ cấp phát cho các đối tượng trước khi hủy một đối tượng. 7.Hàm trùng tên: Hàm trùng tên hay còn gọi là hàm chồng (đè). Đây là một kỹ thuật cho phép sử dụng cùng một tên gọi cho các hàm "giống nhau" (cùng mục đích) nhưng xử lý trên các kiểu dữ liệu khác nhau hoặc trên số lượng dữ liệu khác nhau. -C++, C#, Java cho phép định nghĩa nhiều hàm trùng tên điều kiện: + số lượng các tham đối trong hàm là khác nhau + kiểu của tham đối trong hàm là khác nhau. -C++, C#, Java phân biệt hàm này với hàm khác dựa vào số tham đối và kiểu của các tham đối, bất chấp tên hàm và kiểu của kết quả trả về. Khi không có hàm nào có bộ đối cùng kiểu với bộ tham số(trong lời gọi), thì trình biên dịch sẽ chọn hàm nào có bộ đối gần với phép chuyển kiểu dễ dàng nhất. 8.nhập xuất: có thể chưa thành: + in-out với (màn hình + bàn phím) + in-out với file Theo tác trên 4 loại dữ liệu cơ bản: + text ( tức là in-out dưới dạng đọc/ghi các ký tự ) + byte ( đọc theo từng byte ) + primitive data ( dữ liệu kiểu nguyên thủy như int float long double ) + Object ( các loại đối tượng ) C++: cần phải có header cho việc nhập xuất(file header là tập tin tiêu đề cho các hàm hay các lớp . Nói chung file này dùng để chứa khai báo cho hàm ( nếu là C ) hay cho lớp ( C++ )) Thư viện để nhập xuất bàn phim – màn hình là: iostream.h +Xuất: cout<<bieuthuc…<<bieu thuc +Nhập : cin>>bien>>…>>bien C#: dùng phương thức WriteLine() của lớp Console để xuất ra màn hình dòng lệnh, C# dùng ReadLine() của lớp Console để nhập giá trị vào, Java: Tất cả những hoạt động nhập/xuất dữ liệu (nhập dữ liệu từ bàn phím, lấy dữ liệu từ mạng về, ghi dữ liệu ra đĩa, xuất dữ liệu ra màn hình, máy in, …) đều được quy về một khái niệm gọi là luồng (stream). Luồng là nơi có thể “sản xuất” và “tiêu thụ” thông tin. Thường chúng ta hay nhập xuất kiểu Console. + để xuất ra dòng lệnh ta dùng: system.out.write() + để nhập dòng lệnh giá trị ta dùng : system.in.read() 9.Nhận xét : Ta thấy C# và Java là ngôn ngữ ra đời sau va có thich kế thừa từ C++, cũng như C++ từng kế thừa C. Cho nên ta thấy nó có những thay đổi và cải tiến hay về mặt lập trình. Java và C# đều là ngôn ngữ hướng đối tượng, chúng hỗ trợ mô hình hướng đối tượng khá tốt với mức độ gần như nhau, chúng có cú pháp hầu như giống nhau nên công sức học cả 2 ngôn ngữ không nhiều hơn bao nhiêu so với công sức học 1 trong 2 ngôn ngữ. Tùy thuộc môi trường hoạt động của ứng dụng mà chọn ngôn ngữ nào phù hợp hơn.
File đính kèm:
- Đề tài Điểm giống và khác nhau giữa C++, C# và Java.pdf