it-swarm-vi.com

C khác với C ++ như thế nào?

Nhiều người đã nói rằng C++ là một ngôn ngữ hoàn toàn khác với C, nhưng chính Bjarne đã nói rằng C++ là một ngôn ngữ được mở rộng từ C do đó là nơi ++ đến từ. Vậy tại sao mọi người cứ nói rằng C và C++ là hai ngôn ngữ hoàn toàn khác nhau? C khác với C++ như thế nào ngoài các tính năng mở rộng trong C++?

21
Joshua Partogi

Trong những năm 1980, khi sự phát triển C++ chỉ mới bắt đầu, C++ gần như là một siêu thay thế thích hợp của C. Đó là cách tất cả bắt đầu.
[.__.] Tuy nhiên, theo thời gian, cả C và C++ đã phát triển và đã chuyển hướng khỏi nhau, mặc dù khả năng tương thích giữa các ngôn ngữ luôn được coi là quan trọng.

Ngoài ra, sự khác biệt về kỹ thuật giữa C và C++ đã làm cho các thành ngữ điển hình trong các ngôn ngữ đó và những gì được coi là 'thực hành tốt' phân kỳ hơn nữa.

Đây là yếu tố thúc đẩy mọi người nói những điều như "không có ngôn ngữ nào như C/C++" hay "C và C++ là hai ngôn ngữ khác nhau". Mặc dù có thể viết các chương trình chấp nhận được cho cả trình biên dịch C và C++, nhưng mã này thường được coi là một ví dụ về mã C tốt cũng không phải là ví dụ về mã C++ tốt.

18

Stroustrup tự trả lời rằng trong Câu hỏi thường gặp của anh ấy :

C++ là hậu duệ trực tiếp của C giữ lại gần như toàn bộ C dưới dạng tập hợp con. C++ cung cấp kiểm tra kiểu mạnh hơn C và trực tiếp hỗ trợ nhiều kiểu lập trình hơn C. C++ là "C tốt hơn" theo nghĩa là nó hỗ trợ các kiểu lập trình được thực hiện bằng C với kiểm tra kiểu tốt hơn và hỗ trợ công chứng hơn (không mất về hiệu quả). Theo nghĩa tương tự, ANSI C là C tốt hơn K & R C. Ngoài ra, C++ hỗ trợ trừu tượng hóa dữ liệu, lập trình hướng đối tượng và lập trình chung.

Nó hỗ trợ cho lập trình hướng đối tượng và lập trình chung làm cho C++ "hoàn toàn khác" với C. Bạn có thể gần như viết C thuần túy và sau đó biên dịch nó bằng một Trình biên dịch C++ (miễn là bạn đảm nhiệm việc kiểm tra loại nghiêm ngặt hơn). Nhưng sau đó bạn vẫn đang viết C - bạn không viết C++.

Nếu bạn đang viết C++, thì bạn đang sử dụng các tính năng mẫu và hướng đối tượng của nó và đó không giống như những gì bạn sẽ thấy trong C.

20
Dean Harding

Nói một cách đơn giản, những gì được coi là thành ngữ trong C chắc chắn không phải là thành ngữ trong C++.

C và C++ là những ngôn ngữ rất khác nhau trong thực tế, vì cách mọi người sử dụng chúng. C nhắm đến sự tối giản, trong đó C++ là một ngôn ngữ rất phức tạp, với rất nhiề các tính năng.

Ngoài ra còn có một số khác biệt thực tế: C có thể dễ dàng được gọi từ hầu hết mọi ngôn ngữ và thường định nghĩa ABI của một nền tảng, trong khi C++ khá khó sử dụng từ các thư viện khác. Hầu hết các ngôn ngữ đều có FFI hoặc giao diện bằng C, thậm chí các ngôn ngữ được triển khai trong C++ (ví dụ Java).

13
David Cournapeau

Ngoài thực tế rõ ràng là C++ hỗ trợ lập trình hướng đối tượng, tôi nghĩ bạn có câu trả lời của mình ở đây: http://en.wikipedia.org/wiki/Compabilities_of_C_and_C++

Bài viết đó chứa các ví dụ mã hiển thị nội dung ổn trong C nhưng không có trong C++. Ví dụ:

int *j = malloc(sizeof(int) * 5); /* Implicit conversion from void* to int* */

Chuyển một chương trình C sang C++ thường đơn giản và chủ yếu bao gồm sửa các lỗi biên dịch (thêm phôi, từ khóa mới, v.v.).

4
Martin Wickman

C++ không chỉ bổ sung các tính năng mới mà cả các khái niệm mới và thành ngữ mới cho C. Mặc dù C++ và C có liên quan chặt chẽ với nhau, nhưng thực tế vẫn là để viết hiệu quả bằng ngôn ngữ, bạn phải suy nghĩ theo phong cách của ngôn ngữ đó. Ngay cả mã C tốt nhất cũng không thể tận dụng các điểm mạnh và thành ngữ khác nhau của C++, và do đó nhiều khả năng hơn là không thực sự hơn xấ mã C++.

2
Jon Purdy

"Các tính năng mở rộng", bạn làm cho nó nghe giống như trong C++ mà họ đã thêm như, macro biến đổi hoặc một cái gì đó và đó là nó. "Các tính năng mở rộng" trong C++ là một đại tu hoàn chỉnh của ngôn ngữ và hoàn toàn thay thế các thực tiễn C tốt nhất vì các tính năng C++ mới tốt hơn nhiều so với các tính năng C ban đầu mà các tính năng C ban đầu hoàn toàn và hoàn toàn dư thừa trong phần lớn các trường hợp. Việc gợi ý rằng C++ chỉ đơn thuần là mở rộng C đang gợi ý rằng một chiếc xe tăng chiến đấu hiện đại sẽ mở rộng một butterknife cho mục đích tiến hành chiến tranh.

2
DeadMG

Sự khác biệt là trong C bạn nghĩ theo thủ tục và trong C++, bạn nghĩ theo cách hướng đối tượng. Các ngôn ngữ khá giống nhau nhưng cách tiếp cận rất khác nhau.

1
Ant

Trong khi C++ có thể là một tập hợp siêu C theo thuật ngữ cú pháp - tức là mọi cấu trúc của chương trình C đều có thể được biên dịch bởi trình biên dịch C++.

Tuy nhiên, bạn gần như không bao giờ viết chương trình C++ theo cách bạn đã làm với chương trình C. Danh sách này có thể là vô tận hoặc có thể là một người nào đó nên thực hiện nhiều nghiên cứu hơn để đưa nó thành báo cáo đầy đủ. Tuy nhiên, tôi đang đặt một vài gợi ý làm nên sự khác biệt chính.

Điểm chính của bài viết hiện tại là C++ có các tính năng mà một lập trình viên C++ giỏi phải sử dụng làm thực tiễn tốt nhất cho lập trình mặc dù có thể biên dịch C tương đương.

Nên làm thế nào trong C++ trên C

  1. Lớp học & Kế thừa. Đó là sự khác biệt quan trọng nhất cho phép định hướng đối tượng có hệ thống làm cho biểu thức lập trình trở nên rất mạnh mẽ. Tôi đoán - điểm này không cần giải thích tốt hơn. Nếu bạn ở trong C++ - hầu như luôn luôn, bạn nên sử dụng các lớp tốt hơn.

  2. Tư nhân hóa - Các lớp học, và thậm chí các cấu trúc có những gì là thành viên tư nhân. Điều này làm cho đóng gói của một lớp có thể. Tương đương trong C là bằng cách đánh máy đối tượng thành void * cho ứng dụng để ứng dụng không có quyền truy cập vào các biến nội bộ. Tuy nhiên, trong C++, bạn có thể có các phần tử với các lớp công khai cũng như riêng tư.

  3. Đi qua tham khảo. C++ cho phép sửa đổi dựa trên tham chiếu, trong đó yêu cầu chuyển con trỏ. Tham chiếu qua giữ cho mã rất sạch sẽ và an toàn hơn trước các mối nguy con trỏ. Bạn cũng sử dụng con trỏ kiểu C và nó hoạt động - nhưng nếu bạn ở trong C++, bạn sẽ tốt hơn miễn là

  4. mới và xóa so với malloc và miễn phí. Các câu lệnh mới () và xóa () không chỉ phân bổ và phân bổ bộ nhớ, mà còn cho phép mã thực thi như là một phần của hàm hủy được gọi trong chuỗi. Nếu bạn đang sử dụng C++ - thực sự là BAD để sử dụng malloc và miễn phí.

  5. Các loại IO và quá tải toán tử Quá tải toán tử làm cho mã có thể đọc được hoặc trực quan hơn nếu được thực hiện tốt. Tương tự cho các toán tử << và >> io. Cách C để làm điều này sẽ là sử dụng các con trỏ hàm - nhưng nó lộn xộn và chỉ dành cho các lập trình viên trước.

  6. Sử dụng "chuỗi". Các char * từ C hoạt động ở khắp mọi nơi. Vì vậy, C và C++ khá giống nhau. Tuy nhiên, nếu bạn đang ở trong C++ - thì việc sử dụng các lớp String sẽ giúp bạn tránh khỏi sự nguy hiểm của mảng khi chạy gần như mọi thứ.

Các tính năng tôi vẫn sẽ không phải là fan hâm mộ của C++ 1. Mẫu - Trong khi tôi không sử dụng các mẫu nặng trong nhiều mã - nó có thể rất mạnh cho các thư viện. Hầu như không có tương đương với nó trong C. Nhưng vào một ngày bình thường - đặc biệt nếu bạn đang làm mất tích về mặt toán học.

  1. Con trỏ thông minh - Vâng, chúng rất thông minh! Và giống như hầu hết những điều thông minh - chúng khởi đầu tốt và trở nên lộn xộn sau này! Tôi không thích sử dụng

Những điều tôi thích về C và bỏ lỡ trong C++

  1. Các thuật toán đa hình bằng cách sử dụng các con trỏ hàm. Trong C, khi bạn đang chạy các thuật toán phức tạp - đôi khi bạn có thể sử dụng bộ con trỏ hàm. Điều này làm cho tính đa hình thực sự một cách mạnh mẽ. Khi bạn ở trong C++, bạn [~ # ~] có thể [~ # ~] sử dụng các con trỏ hàm - nhưng điều đó thật tệ. Bạn chỉ nên sử dụng các phương pháp - khác hãy chuẩn bị để có được sự lộn xộn. Dạng đa hình duy nhất trong các lớp C++ là quá tải hàm và toán tử nhưng điều đó khá hạn chế.

  2. Chủ đề đơn giản. Khi bạn tạo chủ đề là pthreads - nó khá đơn giản và dễ quản lý. Nó trở thành khi bạn cần tạo các chủ đề được coi là "riêng tư" cho các lớp (để chúng có quyền truy cập vào các thành viên riêng). Có loại boost loại khung - nhưng không có gì trong C++ cơ bản.

Dipan.

0
Dipan Mehta

Một số tính năng ngôn ngữ, ngay cả khi chúng là bổ sung, có thể thay đổi toàn bộ cách ngôn ngữ thực tế cần được sử dụng. Như một ví dụ xem xét trường hợp này:

lock_mutex(&mutex);

// call some functions
...

unlock_mutex(&mutex);

Nếu đoạn mã trên liên quan đến các chức năng gọi được triển khai trong C++, chúng ta có thể gặp rắc rối, vì bất kỳ cuộc gọi chức năng nào cũng có thể xảy ra và chúng ta sẽ không bao giờ mở khóa mutex trong những đường dẫn đặc biệt đó.

Công cụ phá hủy không còn trong lĩnh vực tiện lợi để giúp các lập trình viên tránh việc quên phát hành/giải phóng tài nguyên tại thời điểm đó. RAII trở thành một yêu cầu thực tế bởi vì nó không khả thi về mặt con người để dự đoán từng dòng mã có thể đưa ra các ví dụ không tầm thường (không đề cập đến việc các dòng đó có thể không ném ngay bây giờ nhưng sau đó có thể thay đổi). Lấy một ví dụ khác:

void f(const Foo* f1)
{
    Foo f2;
    memcpy(&f2, f1, sizeof f2);
    ...
}

Mã như vậy, mặc dù nói chung là vô hại trong C, giống như sự tàn phá của địa ngục trong C++, bởi vì memcpy ủi trên các bit và byte của các đối tượng này và bỏ qua những thứ như các hàm tạo sao chép. Các hàm như memset, realloc, memcpy, v.v., trong khi các công cụ hàng ngày giữa các nhà phát triển C thường xem xét mọi thứ theo cách khá đồng nhất của bit và byte trong bộ nhớ, là không hài hòa với hệ thống loại C++ phức tạp và phong phú hơn. C++ khuyến khích một cái nhìn trừu tượng hơn nhiều về các loại do người dùng định nghĩa.

Vì vậy, những loại điều này không còn cho phép C++, bởi bất kỳ ai đang tìm cách sử dụng nó một cách chính xác, xem nó như một "siêu năng lực" đơn thuần của C. Những ngôn ngữ này đòi hỏi một tư duy, kỷ luật và cách suy nghĩ rất khác nhau để sử dụng một cách hiệu quả nhất .

Tôi không ở trong trại, thấy C++ hoàn toàn tốt hơn về mọi mặt và thực tế hầu hết các lib của bên thứ ba yêu thích của tôi đều là thư viện C vì một số lý do. Tôi không biết tại sao chính xác nhưng C libs có xu hướng tối giản hơn về bản chất (có lẽ vì không có hệ thống kiểu phong phú như vậy khiến các nhà phát triển tập trung hơn vào việc cung cấp chức năng tối thiểu cần thiết mà không cần xây dựng một số trừu tượng lớn và nhiều lớp), mặc dù tôi thường chỉ đặt các trình bao bọc C++ xung quanh chúng để đơn giản hóa và điều chỉnh việc sử dụng chúng cho mục đích của tôi, nhưng bản chất tối giản đó thích hợp với tôi ngay cả khi làm điều đó. Tôi thực sự yêu thích sự tối giản như một tính năng hấp dẫn của một thư viện dành cho những người dành thêm thời gian để tìm kiếm những phẩm chất như vậy, và có lẽ C có xu hướng khuyến khích rằng, nếu chỉ nhờ vào thực tế rằng mã lớn và nhiều lớp như vậy sẽ là một PITA thực sự để phát triển ở C.

Tôi thích C++ thường xuyên hơn không, nhưng tôi thực sự bắt buộc phải sử dụng API C thường xuyên hơn để có khả năng tương thích nhị phân rộng nhất (và cho FFI), mặc dù tôi thường triển khai chúng trong C++ mặc dù sử dụng C cho các tiêu đề. Nhưng đôi khi khi bạn thực sự ở mức độ thấp, như mức phân bổ bộ nhớ hoặc cấu trúc dữ liệu ở mức rất thấp (và tôi chắc chắn có những ví dụ khác trong số những người làm lập trình nhúng), đôi khi có thể hữu ích khi có thể giả định rằng các loại và dữ liệu bạn đang làm việc không có các tính năng nhất định như vtables, trình xây dựng và hàm hủy, để chúng ta có thể coi chúng là các bit và byte để xáo trộn xung quanh, sao chép, miễn phí, phân bổ lại. Đối với các vấn đề rất đặc biệt ở cấp độ thấp, đôi khi có thể hữu ích khi làm việc với một hệ thống loại đơn giản hơn nhiều mà C cung cấp, và tất nhiên nó có xu hướng xây dựng nhanh hơn và hơn thế nữa.

Làm rõ

Một nhận xét thú vị ở đây tôi muốn trả lời sâu hơn một chút (tôi thấy các nhận xét ở đây rất nghiêm ngặt về giới hạn ký tự):

memcpy(&f2, f1, sizeof f2); cũng là "địa ngục trị vì" trong Foo nếu Foo có bất kỳ con trỏ sở hữu nào, hoặc thậm chí tệ hơn, vì bạn cũng thiếu công cụ để đối phó với điều đó.

Đó là một điểm công bằng nhưng mọi thứ tôi tập trung chủ yếu tập trung vào hệ thống loại của C++ và cũng liên quan đến RAII. Một trong những lý do sao chép byte x-rayish memcpy hoặc qsort ít gây nguy hiểm thực tế trong C là việc phá hủy f1f2 Ở trên là rõ ràng (nếu chúng thậm chí cần phá hủy không tầm thường), trong khi đó khi các hàm hủy di chuyển vào hình ảnh, chúng trở nên ẩn và tự động (thường có giá trị lớn cho các nhà phát triển). Điều đó thậm chí không đề cập đến trạng thái ẩn như vptrs và do đó các chức năng như vậy sẽ ủi đất ngay. Nếu f1 Sở hữu con trỏ và f2 Sao chép chúng trong một số ngữ cảnh tạm thời, thì sẽ không có vấn đề gì nếu chúng ta không cố gắng giải phóng rõ ràng những con trỏ sở hữu đó lần thứ hai. Với C++, đó là điều mà trình biên dịch sẽ tự động muốn làm.

Và điều đó trở nên lớn hơn nếu thường ở C, " If Foo có sở hữu con trỏ ", bởi vì nhân chứng cần thiết với quản lý tài nguyên thường sẽ khiến cho thứ gì đó thường khó bỏ qua hơn trong khi trong C++, chúng ta có thể tạo một UDT không còn có thể xây dựng/phá hủy một cách tầm thường bằng cách chỉ lưu trữ bất kỳ biến thành viên nào không phải là ' t có thể xây dựng/phá hủy tầm thường (theo cách nói chung là rất hữu ích, nhưng không phải nếu chúng ta muốn sử dụng các chức năng như memcpy hoặc realloc).

Quan điểm chính của tôi là không cố gắng tranh luận bất kỳ lợi ích nào của nhà thám hiểm này (tôi sẽ nói nếu có bất kỳ điều gì, họ hầu như luôn bị đè nặng bởi những khuyết điểm về xác suất gia tăng của lỗi con người đi kèm với nó), mà chỉ để nói rằng các hàm như memcpymemmoveqsortmemsetrealloc và vv không có chỗ nào trong ngôn ngữ có UDTs phong phú như vậy tính năng và khả năng như C++. Mặc dù chúng tồn tại bất kể, tôi nghĩ sẽ không quá tranh cãi khi nói rằng đại đa số các nhà phát triển C++ sẽ là khôn ngoan để tránh các chức năng như bệnh dịch, trong khi đó là các loại chức năng rất hàng ngày trong C, và tôi d lập luận rằng họ đặt ra ít vấn đề hơn trong C vì lý do đơn giản là hệ thống loại của nó cơ bản hơn rất nhiều và có lẽ là "ngu ngốc". Các loại C tia X và coi chúng là bit và byte dễ bị lỗi. Làm điều đó trong C++ được cho là hoàn toàn sai lầm vì các chức năng như vậy đang chống lại các tính năng rất cơ bản của ngôn ngữ và những gì nó khuyến khích của hệ thống loại.

Đó thực sự là điểm hấp dẫn nhất đối với tôi của C, tuy nhiên, đặc biệt với cách nó liên quan đến khả năng tương tác ngôn ngữ. Sẽ rất khó khăn hơn nhiều để làm cho một cái gì đó như FFI của C # hiểu được hệ thống loại hoàn chỉnh và các tính năng ngôn ngữ của C++ xuống các hàm tạo, hàm hủy, ngoại lệ, hàm ảo, nạp chồng hàm/phương thức, quá tải toán tử, tất cả các loại khác nhau của kế thừa, v.v ... Với C, ngôn ngữ tương đối ngu ngốc đã trở nên khá chuẩn như API theo cách mà nhiều ngôn ngữ khác nhau có thể nhập trực tiếp qua FFI hoặc gián tiếp thông qua một số hàm xuất API C ở dạng mong muốn (ví dụ: Java Giao diện gốc). Và đó là nơi tôi hầu như không còn lựa chọn nào khác ngoài sử dụng C, vì khả năng tương tác ngôn ngữ đó là một yêu cầu thiết thực trong trường hợp của chúng tôi (mặc dù tôi thường chỉ viết giao diện C với C++ thực hiện đằng sau chúng).

Nhưng bạn biết đấy, tôi là một người thực dụng (hoặc ít nhất là tôi phấn đấu). Nếu C là ngôn ngữ khó chịu và đáng tin cậy, dễ bị lỗi, khó chịu này, một số đồng nghiệp đam mê C++ của tôi đã tuyên bố đó là (và tôi tự coi mình là người đam mê C++ ngoại trừ việc bằng cách nào đó nó không dẫn đến sự ghét bỏ C ; ngược lại, nó có tác dụng ngược lại đối với tôi khi khiến tôi đánh giá cao cả hai ngôn ngữ tốt hơn ở khía cạnh và sự khác biệt của chúng), sau đó tôi hy vọng rằng nó sẽ xuất hiện trong thế giới thực dưới dạng một số lỗi nhất và rò rỉ nhất và các sản phẩm và thư viện không đáng tin cậy được viết bằng C. Và tôi không tìm thấy điều đó. Tôi thích Linux, tôi thích Apache, Lua, zlib, tôi thấy OpenGL có thể chấp nhận được vì di sản lâu dài của nó chống lại các yêu cầu phần cứng thay đổi như vậy, Gimp, libpng, Cairo, v.v ... Ít nhất là bất cứ điều gì cản trở ngôn ngữ đặt ra dường như không gây ra sự bế tắc viết một số thư viện và sản phẩm tuyệt vời trong tay có thẩm quyền, và đó thực sự là tất cả những gì tôi quan tâm. Vì vậy, tôi chưa bao giờ là loại người quan tâm đến các cuộc chiến ngôn ngữ đam mê nhất, ngoại trừ để đưa ra một lời kêu gọi thực dụng và nói: "Này, có Những thứ hay ho ở ngoài kia! Hãy tìm hiểu cách họ tạo ra nó và có thể có những bài học hay, không quá cụ thể về bản chất thành ngữ của ngôn ngữ, mà chúng ta có thể đưa trở lại bất kỳ ngôn ngữ nào chúng ta đang sử dụng. " : -D

0
Dragon Energy