Chuyển từ C ++ sang C


83

Sau một vài năm viết mã bằng C ++, gần đây tôi đã được mời làm công việc viết mã bằng C, trong lĩnh vực nhúng.

Bỏ qua câu hỏi liệu việc loại bỏ C ++ trong lĩnh vực nhúng là đúng hay sai, có một số tính năng / thành ngữ trong C ++ mà tôi sẽ bỏ lỡ rất nhiều. Chỉ để kể tên một vài:

  • Cấu trúc dữ liệu chung kiểu, an toàn (sử dụng mẫu).
  • RAII. Đặc biệt là trong các hàm có nhiều điểm trả về, ví dụ như không phải nhớ giải phóng mutex trên mỗi điểm trả về.
  • Kẻ hủy diệt nói chung. Tức là bạn viết một d'tor một lần cho MyClass, sau đó nếu một cá thể MyClass là thành viên của MyOtherClass, MyOtherClass không phải định nghĩa rõ ràng cá thể MyClass - d'tor của nó được gọi tự động.
  • Không gian tên.

Kinh nghiệm của bạn khi chuyển từ C ++ sang C là gì?
Bạn đã tìm thấy sản phẩm thay thế C nào cho các tính năng / thành ngữ C ++ yêu thích của mình? Bạn có phát hiện ra bất kỳ tính năng C nào mà bạn muốn C ++ có không?


12
Có lẽ nên là wiki cộng đồng nếu bạn chỉ hỏi kinh nghiệm chứ không phải lời khuyên.
Peter Alexander

6
Bạn có thể quan tâm đến Prog.SE .

11
@Peter: OP không thể đưa ra câu hỏi cho CW nữa, và nó yêu cầu nhiều đại diện hơn anh ấy có khi vẫn có thể. Nếu bạn nghĩ rằng một câu hỏi nên được đưa ra wiki cộng đồng vì bất kỳ lý do nào khác ngoài việc cho phép nhiều người dùng chỉnh sửa các bài đăng "thuộc sở hữu của cộng đồng", thì điều bạn thực sự muốn là đóng câu hỏi.

4
Câu hỏi này sẽ không phù hợp hơn với các lập trình viên.se sao? Vì nó chắc chắn là một câu hỏi "thực sự", tôi nói rằng chúng tôi mở lại nó và bỏ phiếu để chuyển nó đi. Và điều đó là không thể. ĐỒNG Ý.
Lasse V. Karlsen

21
Việc di chuyển sẽ không xảy ra cho đến khi prog SE hết phiên bản beta và trong mọi trường hợp, tôi nghĩ rằng cách tiếp cận QA này đang làm hỏng braindead. Nó phân mảnh cộng đồng, gây khó chịu cho người dùng, trùng lặp các câu hỏi và câu trả lời. Nó tạo ra một mớ hỗn độn về thông tin không được tổ chức mà trước đây có thể truy cập và điều hướng được trên một trang web "lập trình viên". Ngoài ra, những câu hỏi như thế này, có lượt xem lớn và sự ủng hộ đáng kinh ngạc, khiến tôi tức giận giữa 5 người gần gũi hơn và cả cộng đồng nói chung.
Stefano Borini

Câu trả lời:


68

Làm việc trong một dự án nhúng, tôi đã thử làm việc trong tất cả C một lần, và chỉ không thể chịu được. Nó chỉ dài dòng đến mức khiến bạn khó đọc bất cứ thứ gì. Ngoài ra, tôi thích các vùng chứa được tối ưu hóa cho nhúng mà tôi đã viết, chúng phải biến thành #definecác khối kém an toàn và khó sửa hơn nhiều .

Mã trong C ++ trông giống như:

if(uart[0]->Send(pktQueue.Top(), sizeof(Packet)))
    pktQueue.Dequeue(1);

trở thành:

if(UART_uchar_SendBlock(uart[0], Queue_Packet_Top(pktQueue), sizeof(Packet)))
    Queue_Packet_Dequeue(pktQueue, 1);

mà nhiều người có thể sẽ nói là tốt nhưng sẽ thật nực cười nếu bạn phải thực hiện nhiều hơn một vài lệnh gọi "method" trong một dòng. Hai dòng C ++ sẽ biến thành năm dòng C (do giới hạn độ dài dòng 80 ký tự). Cả hai sẽ tạo ra cùng một mã, vì vậy nó không giống như bộ xử lý đích quan tâm!

Một lần (trở lại năm 1995), tôi đã thử viết rất nhiều C cho một chương trình xử lý dữ liệu đa bộ xử lý. Loại mà mỗi bộ xử lý có bộ nhớ và chương trình riêng. Trình biên dịch do nhà cung cấp cung cấp là trình biên dịch C (một số loại dẫn xuất HighC), các thư viện của họ là mã nguồn đóng nên tôi không thể sử dụng GCC để xây dựng và các API của họ được thiết kế với suy nghĩ rằng chương trình của bạn chủ yếu sẽ là quá trình / khởi tạo / chấm dứt sự đa dạng, vì vậy giao tiếp giữa các bộ xử lý tốt nhất là thô sơ.

Tôi đã có khoảng một tháng trước khi từ bỏ, tìm thấy một bản sao của cfront và hack nó vào trang điểm để tôi có thể sử dụng C ++. Cfront thậm chí không hỗ trợ các mẫu, nhưng mã C ++ rõ ràng hơn rất nhiều.

Cấu trúc dữ liệu chung kiểu, an toàn (sử dụng mẫu).

Điều gần nhất mà C có với các mẫu là khai báo một tệp tiêu đề với rất nhiều mã giống như:

TYPE * Queue_##TYPE##_Top(Queue_##TYPE##* const this)
{ /* ... */ }

sau đó kéo nó vào với một cái gì đó như:

#define TYPE Packet
#include "Queue.h"
#undef TYPE

Lưu ý rằng điều này sẽ không hoạt động đối với các loại phức hợp (ví dụ: không có hàng đợi unsigned char) trừ khi bạn thực hiện typedeftrước.

Ồ, và hãy nhớ rằng, nếu mã này thực sự không được sử dụng ở bất kỳ đâu, thì bạn thậm chí không biết liệu nó có chính xác về mặt cú pháp hay không.

CHỈNH SỬA: Một điều nữa: bạn sẽ cần quản lý việc khởi tạo mã theo cách thủ công . Nếu mã "mẫu" của bạn không phải là tất cả các chức năng nội tuyến, thì bạn sẽ phải đặt một số kiểm soát để đảm bảo rằng mọi thứ chỉ được khởi tạo một lần để trình liên kết của bạn không tạo ra một đống lỗi "nhiều trường hợp của Foo" .

Để làm điều này, bạn sẽ phải đặt nội dung không được nội tuyến trong phần "triển khai" trong tệp tiêu đề của mình:

#ifdef implementation_##TYPE

/* Non-inlines, "static members", global definitions, etc. go here. */

#endif

Và sau đó, ở một nơi trong tất cả mã của bạn cho mỗi biến thể mẫu , bạn phải:

#define TYPE Packet
#define implementation_Packet
#include "Queue.h"
#undef TYPE

Ngoài ra, phần triển khai này cần phải nằm ngoài tiêu chuẩn #ifndef/ #define/ #endiflitany, vì bạn có thể bao gồm tệp tiêu đề mẫu trong tệp tiêu đề khác, nhưng cần phải khởi tạo sau đó trong .ctệp.

Đúng, nó trở nên xấu đi nhanh chóng. Đó là lý do tại sao hầu hết các lập trình viên C thậm chí không thử.

RAII.

Đặc biệt là trong các hàm có nhiều điểm trả về, ví dụ như không phải nhớ giải phóng mutex trên mỗi điểm trả về.

Chà, quên đoạn mã đẹp đẽ của bạn và làm quen với tất cả các điểm trả về của bạn (ngoại trừ phần cuối của hàm) goto:

TYPE * Queue_##TYPE##_Top(Queue_##TYPE##* const this)
{
    TYPE * result;
    Mutex_Lock(this->lock);
    if(this->head == this->tail)
    {
        result = 0;
        goto Queue_##TYPE##_Top_exit:;
    }

    /* Figure out `result` for real, then fall through to... */

Queue_##TYPE##_Top_exit:
    Mutex_Lock(this->lock);
    return result;
}

Kẻ hủy diệt nói chung.

Tức là bạn viết một d'tor một lần cho MyClass, sau đó nếu một cá thể MyClass là thành viên của MyOtherClass, MyOtherClass không phải định nghĩa rõ ràng cá thể MyClass - d'tor của nó được gọi tự động.

Việc xây dựng đối tượng phải được xử lý rõ ràng theo cùng một cách.

Không gian tên.

Đó thực sự là một cách khắc phục đơn giản: chỉ cần gắn một tiền tố vào mỗi biểu tượng. Đây là nguyên nhân chính gây ra hiện tượng phồng nguồn mà tôi đã nói trước đó (vì các lớp là không gian tên ngầm định). Những người C đã sống như vậy, tốt, mãi mãi, và có lẽ sẽ không thấy vấn đề lớn là gì.

YMMV


59
Tất nhiên bạn ghét C nếu bạn cố ép nó là C ++. Tôi nghi ngờ rằng C ++ sẽ trông tuyệt vời nếu bạn cố gắng áp đặt các tính năng từ $ more_expressive_language vào nó. Không phải là một bài phê bình để bài viết của bạn, chỉ cần một quan sát :-)

Về kỹ thuật goto-thay-vì-RAII: Nó không phải là một cơn ác mộng bảo trì sao? tức là bất cứ khi nào bạn thêm một đường dẫn mã cần dọn dẹp, hoặc thậm chí chỉ cần thay đổi thứ tự của những thứ bên trong hàm, bạn phải nhớ chuyển đến nhãn goto ở cuối và thay đổi chúng. Tôi muốn xem một kỹ thuật bằng cách nào đó đăng ký mã dọn dẹp ngay bên cạnh những gì cần được dọn dẹp.
george

2
@george: Tôi ghét phải nói điều đó, nhưng hầu hết mã C nhúng mà tôi đã thấy là khá tệ theo tiêu chuẩn C. Ví dụ: tôi đang làm việc với at91lib của Atmel ngay bây giờ và nó yêu cầu bạn viết một tệp "board.h" mà phần lớn mã của họ kéo vào dưới dạng phụ thuộc. (Đối với bảng demo của họ, tiêu đề này có chiều dài 792 dòng.) Ngoài ra, một "LowLevelInit ()" chức năng mà bạn phải tùy chỉnh cho hội đồng quản trị của bạn là gần như hoàn toàn đăng ký truy cập, với những đường nét nhưAT91C_BASE_PMC->PMC_MOR = (0x37 << 16) | BOARD_OSCOUNT | AT91C_CKGR_MOSCRCEN | AT91C_CKGR_MOSCXTEN | AT91C_CKGR_MOSCSEL;
Mike Desimone

1
Ồ, và không có gì ở đó cho bạn biết rằng BOARD_OSCOUNT(giá trị của thời gian chờ đợi đồng hồ chuyển đổi; rõ ràng, huh?) Thực sự là một #definetrong board.h. Ngoài ra, trong cùng một chức năng đó, rất nhiều mã vòng lặp spin sao chép và dán, lẽ ra phải được chuyển thành một dòng hai #define(và khi tôi làm điều đó, nó đã lưu một vài byte mã và làm cho chức năng dễ đọc hơn bằng cách làm cho các bộ thanh ghi và các vòng quay khác biệt hơn). Một trong những lý do lớn để sử dụng C là nó cho phép bạn quản lý vi mô và tối ưu hóa mọi thứ, nhưng hầu hết các mã tôi đã thấy đều không bận tâm.
Mike DeSimone

5
Đồng ý với @Mads. Không có lý do gì để trải qua tất cả những điều đó cho các tính năng bạn không thực sự cần. Tôi thấy mình thích một phong cách tương tự như thư viện GTK. Xác định "các lớp" của bạn dưới dạng cấu trúc và sau đó tạo các phương thức nhất quán chẳng hạn như my_class_new () và sau đó chuyển nó vào "phương thức": my_class_do_this (my_class_instance)
Tối đa

17

Tôi đã chuyển từ C ++ sang C vì một lý do khác (một số loại phản ứng dị ứng;) và chỉ có một số điều mà tôi nhớ và một số điều mà tôi đã đạt được. Nếu bạn gắn bó với C99, nếu bạn có thể, có những cấu trúc cho phép bạn lập trình khá độc đáo và an toàn, đặc biệt

  • các trình khởi tạo được chỉ định (cuối cùng được kết hợp với macro) làm cho việc khởi tạo các lớp đơn giản trở nên dễ dàng như các hàm tạo
  • các ký tự ghép cho các biến tạm thời
  • for-biến kính có thể giúp bạn quản lý tài nguyên bị ràng buộc phạm vi , đặc biệt là để đảm bảo unlockmutexes hoặc freemảng, ngay cả khi trả về hàm sơ bộ
  • __VA_ARGS__ macro có thể được sử dụng để có các đối số mặc định cho các hàm và để thực hiện việc giải mã
  • inline các hàm và macro kết hợp tốt để thay thế (loại) các hàm quá tải

2
@Mike: cụ thể là cho phần nào vậy? Nếu bạn theo liên kết mà tôi đã cung cấp cho forphạm vi, bạn sẽ đến P99, nơi bạn cũng có thể tìm kiếm các ví dụ và mô tả về các phần khác.
Jens Gustedt

1
@Mike: Được rồi.
george

@george: Cảm ơn! @Jens: Ví dụ về bốn cái còn lại. Tôi đã bị tụt lại phía sau điểm C của mình; cuối cùng tôi nghe nói rằng họ đã thêm các mảng được cấp phát tự động (ví dụ: ngăn xếp) có kích thước thời gian chạy (ví dụ void DoSomething(unsigned char* buf, size_t bufSize) { unsigned char temp[bufSize]; ... }) và khởi tạo cấu trúc bằng tên trường (ví dụ struct Foo bar = { .field1 = 5, .field2 = 10 };), cái sau mà tôi muốn thấy trong C ++, đặc biệt là với các đối tượng không phải POD (ví dụ UART uart[2] = { UART(0x378), UART(0x278) };) .
Mike DeSimone

@Mike: vâng, có các mảng độ dài thay đổi (VLA), nhưng chúng có thể hơi nguy hiểm khi sử dụng vì có khả năng xảy ra hiện tượng stackoverflow. Thứ hai mà bạn mô tả chính xác là "bộ khởi tạo được chỉ định", vì vậy, bạn có thể lấy ví dụ của riêng mình ;-) Đối với những người khác, bạn tìm thấy thông tin trên liên kết P99 ở trên nếu bạn nhấp vào "Trang liên quan".
Jens Gustedt,

8

Không có gì giống như STL tồn tại cho C.
Có sẵn các lib cung cấp chức năng tương tự, nhưng nó không còn là nội trang nữa.

Hãy nghĩ rằng đó sẽ là một trong những vấn đề lớn nhất của tôi ... Biết mình có thể giải quyết vấn đề bằng công cụ nào, nhưng không có sẵn công cụ bằng ngôn ngữ mà tôi phải sử dụng.


điều này là đúng. có ai có thể giải thích về những thư viện lớp chứa nào nên sử dụng cho C không? Hay câu trả lời là "tự viết một cái"?
Sandeep

@Sandeep: Đối với người mới bắt đầu, câu trả lời này chỉ đúng về các vùng chứa không nằm trong lib tiêu chuẩn. Ngoài việc thiếu STL tương đương (phần tốt nhất của C ++), thư viện tiêu chuẩn C còn vượt trội hơn nhiều. POSIX chứa tsearch, lsearch, hsearch và bsearch ngoài qsort có trong libc. Glib là "Boost" chính xác của C, hãy xem nó được đóng gói với các món quà (bao gồm hộp đựng). thư viện.gnome.org/devel/glib/stable . Glib cũng tích hợp với Gtk +, một sự kết hợp vượt quá Boost và Qt. Ngoài ra còn có libapr, phổ biến cho các công cụ xplatform như Subversion và Apache.
Matt Joiner

Tôi không thể tìm thấy bất kỳ lib nào của c có thể cạnh tranh với stl, chúng khó sử dụng hơn, khó bảo trì hơn, hiệu suất không phải là đối thủ của stl khi họ muốn giữ các lib c chung chung như stl. hạn chế của c, và lý do tại sao chúng ta không thể có một cái gì đó giống như stl trong thư viện c, bởi vì c đơn giản là không có khả năng phát triển một cái gì đó như stl.
StereoMatching

8

Sự khác biệt giữa C và C ++ là khả năng dự đoán hành vi của mã.

Dự đoán dễ dàng hơn với độ chính xác cao mã của bạn sẽ làm gì trong C, trong C ++, việc đưa ra dự đoán chính xác có thể trở nên khó khăn hơn một chút.

Khả năng dự đoán trong C cho phép bạn kiểm soát tốt hơn những gì mã của bạn đang làm, nhưng điều đó cũng có nghĩa là bạn phải làm nhiều thứ hơn.

Trong C ++, bạn có thể viết ít mã hơn để hoàn thành công việc tương tự, nhưng (đối với tôi), đôi khi tôi gặp khó khăn khi biết cách mã đối tượng được trình bày trong bộ nhớ và hành vi của nó như mong đợi.


4
Bất cứ khi nào tôi lo lắng về những gì mã thực sự đang làm, tôi thêm -scờ gccđể lấy kết xuất lắp ráp, tìm kiếm hàm quan tâm và bắt đầu đọc. Đó là một cách tuyệt vời để học bất kỳ câu nào của ngôn ngữ biên dịch.
Mike DeSimone

2
Nó cũng lãng phí thời gian, xem như hợp ngữ được tạo C ++ sẽ giống như đọc Perl. Xin chúc mừng vì đã tìm kiếm dù sao.
Matt Joiner

7

Trong dòng công việc của tôi - nhân tiện, được nhúng - tôi liên tục chuyển đổi qua lại giữa C và C ++.

Khi tôi học C, tôi bỏ lỡ C ++:

  • mẫu (bao gồm nhưng không giới hạn ở vùng chứa STL). Tôi sử dụng chúng cho những thứ như bộ đếm đặc biệt, vùng đệm, v.v. (đã xây dựng thư viện mẫu lớp & mẫu hàm của riêng tôi mà tôi sử dụng trong các dự án nhúng khác nhau)

  • thư viện tiêu chuẩn rất mạnh mẽ

  • trình hủy, tất nhiên làm cho RAII khả thi (mutexes, ngắt ngắt, truy tìm, v.v.)

  • truy cập các chỉ định, để thực thi tốt hơn ai có thể sử dụng (không xem) cái gì

Tôi sử dụng tính năng kế thừa trên các dự án lớn hơn và hỗ trợ tích hợp của C ++ dành cho nó gọn gàng và đẹp hơn nhiều so với việc C "hack" nhúng lớp cơ sở làm thành viên đầu tiên (chưa kể đến việc tự động gọi các hàm tạo, init. List, v.v. ) nhưng những món được liệt kê ở trên là những món tôi nhớ nhất.

Ngoài ra, có lẽ chỉ khoảng một phần ba các dự án C ++ nhúng mà tôi làm việc sử dụng các ngoại lệ, vì vậy tôi đã quen với việc sống thiếu chúng, vì vậy tôi không nhớ chúng quá nhiều khi chuyển về C.

Mặt khác, khi tôi quay lại một dự án C với một số lượng đáng kể các nhà phát triển, có rất nhiều vấn đề về C ++ mà tôi quen giải thích với mọi người. Chủ yếu là các vấn đề do sự phức tạp của C ++ và những người nghĩ rằng họ biết chuyện gì đang xảy ra, nhưng họ thực sự đang ở phần "C với các lớp" của đường cong tin cậy C ++ .

Với sự lựa chọn, tôi thích sử dụng C ++ trong một dự án hơn, nhưng chỉ khi nhóm khá vững về ngôn ngữ này. Tất nhiên, giả sử đó không phải là một dự án 8K μC mà tôi đang viết "C" một cách hiệu quả.


2
"Đường cong tin cậy C ++" đó làm phiền tôi một chút. Cách nó được viết và các bình luận, ngụ ý rằng C ++ là vô vọng, một nguyên nhân mất mát, hoặc bất cứ điều gì. Tui bỏ lỡ điều gì vậy?
Mike DeSimone

Hãy lao vào, chúng ta sẽ gặp lại bạn sau vài năm nữa. Hầu hết các lập trình viên giỏi đều cảm thấy khó chịu.
Matt Joiner

3

Một số quan sát

  • Trừ khi bạn định sử dụng trình biên dịch c ++ của mình để xây dựng C của mình (điều này có thể xảy ra nếu bạn bám vào một tập con định nghĩa rõ ràng của C ++), bạn sẽ sớm phát hiện ra những thứ mà trình biên dịch của bạn cho phép trong C đó sẽ là một lỗi biên dịch trong C ++.
  • Không còn lỗi mẫu khó hiểu nữa (yay!)
  • Không (hỗ trợ ngôn ngữ) lập trình hướng đối tượng

C không hỗ trợ mẫu không có nghĩa là chúng ta không cần "mô hình chung", trong C bạn phải sử dụng void * và macro để bắt chước mẫu nếu bạn cần "mô hình chung" .void * không phải là kiểu an toàn, lỗi của macro cũng khá rắc rối, không tốt hơn mẫu. Bản mẫu dễ đọc và dễ bảo trì hơn nhiều so với macro, cộng với loại an toàn.
StereoMatching

2

Khá nhiều lý do giống nhau để tôi sử dụng C ++ hoặc hỗn hợp C / C ++ thay vì thuần C. Tôi có thể sống mà không có không gian tên nhưng tôi sử dụng chúng mọi lúc nếu tiêu chuẩn mã cho phép. Lý do là bạn có thể viết mã nhỏ gọn hơn nhiều trong C ++. Điều này rất hữu ích đối với tôi, tôi viết các máy chủ bằng C ++ có xu hướng bị lỗi ngay bây giờ và sau đó. Tại thời điểm đó, nó sẽ giúp ích rất nhiều nếu mã bạn đang xem là ngắn và nhất quán. Ví dụ, hãy xem xét đoạn mã sau:

uint32_t 
ScoreList::FindHighScore(
  uint32_t p_PlayerId)
{
  MutexLock lock(m_Lock); 

  uint32_t highScore = 0; 
  for(int i = 0; i < m_Players.Size(); i++)
  {
    Player& player = m_Players[i]; 
    if(player.m_Score > highScore)
      highScore = player.m_Score; 
  }

  return highScore; 
}

Trong C trông giống như:

uint32_t 
ScoreList_getHighScore(
  ScoreList* p_ScoreList)
{
  uint32_t highScore = 0; 

  Mutex_Lock(p_ScoreList->m_Lock); 

  for(int i = 0; i < Array_GetSize(p_ScoreList->m_Players); i++)
  {
    Player* player = p_ScoreList->m_Players[i]; 
    if(player->m_Score > highScore)
      highScore = player->m_Score; 
  }

  Mutex_UnLock(p_ScoreList->m_Lock);

  return highScore; 
}

Không phải là một thế giới của sự khác biệt. Một dòng mã nữa, nhưng điều đó có xu hướng cộng lại. Trên danh nghĩa, bạn cố gắng hết sức để giữ cho nó sạch sẽ và gọn gàng nhưng đôi khi bạn phải làm điều gì đó phức tạp hơn. Và trong những tình huống đó, bạn coi trọng số lượng dòng của mình. Một dòng nữa là một điều nữa cần xem xét khi bạn cố gắng tìm ra lý do tại sao mạng quảng bá của bạn đột ngột ngừng gửi tin nhắn.

Dù sao thì tôi thấy rằng C ++ cho phép tôi làm những việc phức tạp hơn một cách an toàn.


Trong C, bạn không thể thực hiện việc này "for (int i = 0".
Victor

6
Victor nó là c99 hợp lệ mặc dù (hoặc biên dịch c bằng trình biên dịch c ++ cho một số vấn đề về đánh máy).
Roman A. Taycher,

Tôi thấy mình không thể tin tưởng vào sự an toàn. Vì vậy, mutex của bạn đã được xác định phạm vi. Bây giờ bạn không biết tại sao nó được mở khóa nên một ngoại lệ "đi lang thang" qua. Bạn thậm chí không biết khi nào nó sẽ được mở khóa, bất kỳ phần nào trong mã của bạn có thể quyết định rằng nó đã đủ và ném. Những "an toàn" ngầm thừa đó có thể là lỗi che dấu.
Matt Joiner

Matt, chúng tôi biết tại sao nó lại mở khóa, trong trường hợp bình thường, khi chương trình đi đến cuối phạm vi, mutex sẽ mở khóa, chúng tôi không cần phải mở khóa bằng mã làm bằng tay, đó là một cơn ác mộng bảo trì. ngoại lệ xảy ra, mutex sẽ được mở khóa và chúng tôi có thể bắt ngoại lệ và đọc thông báo lỗi từ nó. Thông báo lỗi có đủ tốt hay không sẽ phụ thuộc vào cách bạn chơi với ngoại lệ.
StereoMatching

0

Tôi nghĩ vấn đề chính tại sao c ++ khó được chấp nhận hơn trong môi trường nhúng là do thiếu kỹ sư hiểu cách sử dụng c ++ đúng cách.

Đúng, lý do tương tự cũng có thể được áp dụng cho C, nhưng may mắn là không có quá nhiều cạm bẫy trong C có thể bắn vào chân bạn. Mặt khác, trong C ++, bạn cần biết khi nào không nên sử dụng một số tính năng nhất định trong c ++.

Nói chung, tôi thích c ++. Tôi sử dụng nó trên lớp dịch vụ O / S, trình điều khiển, mã quản lý, v.v. Nhưng nếu nhóm của bạn không có đủ kinh nghiệm với nó, đó sẽ là một thử thách khó khăn.

Tôi đã có kinh nghiệm với cả hai. Khi phần còn lại của đội chưa sẵn sàng cho nó, đó là một thảm họa toàn diện. Mặt khác, đó là một kinh nghiệm tốt.


0

Đúng! tôi đã trải nghiệm cả hai ngôn ngữ này và những gì tôi nhận thấy là C ++ là ngôn ngữ thân thiện hơn. Nó tạo điều kiện với nhiều tính năng hơn. Tốt hơn nên nói rằng C ++ là tập hợp siêu ngôn ngữ C vì nó cung cấp các tính năng bổ sung như đa hình, tính tương tác, toán tử và nạp chồng hàm, kiểu dữ liệu do người dùng xác định không thực sự được hỗ trợ trong C. Hàng nghìn dòng mã được giảm xuống còn vài dòng với sự trợ giúp của lập trình hướng đối tượng đó là lý do chính của việc chuyển từ C sang C ++.


C ++ thực sự không phải là một tập siêu của C; rất dễ viết mã C mà sẽ không biên dịch được trên trình biên dịch C ++. Mặt khác, Objective-C là (là?) Một tập hợp siêu nghiêm ngặt của C.
ex nihilo

@exnihilo Tập hợp quy ước ở đây là xác định rằng C ++ đi kèm với nhiều tính năng hơn. Nó cũng cải thiện cú pháp và ngữ nghĩa và giảm khả năng mắc lỗi. Có một số mã không biên dịch trong C ++ nhưng có thể trong C, như const int a; Điều này sẽ gây ra lỗi trong C ++ vì cần phải khởi tạo một hằng số tại thời điểm khai báo trong khi trong C khái niệm sẽ biên dịch. Vì vậy, superset không phải là một quy tắc cứng và nhanh như trong toán học (A⊂B) mà nó là một phép gần đúng mà C ++ cung cấp các tính năng bổ sung như khái niệm hướng đối tượng.
kaynat liaqat
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.