Điều gì làm cho một chương trình (trong một ngôn ngữ như C ++) đa nền tảng hay không?


8

Tôi có kinh nghiệm lập trình khá cơ bản với Java và tôi đã thử C ++ và Python. Mặc dù có ý nghĩa đối với Java, các chương trình cơ bản mà tôi đã viết bằng C ++ đã chạy tốt trên Windows và OS X. Tôi đã có thể gửi tệp nguồn tới máy tính khác, biên dịch và chạy. Các chương trình này khá cơ bản, chủ yếu chỉ là những thứ hướng đối tượng cơ bản mà tôi đang làm để cố gắng học C ++.

Rõ ràng, mặc dù, bạn không thể biên dịch bất kỳ chương trình C ++ nào trên bất kỳ máy nào và để nó chạy tốt. Tại thời điểm nào điều đó xảy ra? Ở mức độ phức tạp nào thì nền tảng bắt đầu có vấn đề và chương trình sẽ không chạy ở bất cứ đâu? Có phải khi bạn sử dụng các thư viện nền tảng cụ thể? Một chương trình có thể được tạo nền tảng chéo trong C ++ chỉ bằng cách sử dụng các thư viện đa nền tảng?

Tôi đã cố gắng tự mình tìm ra điều này nhưng mọi thứ tôi tìm thấy đều nằm trên đầu hoặc đơn giản là không trả lời được câu hỏi, phần lớn những gì được đưa ra là trình giả lập hoặc mọi người hỏi ngôn ngữ nào là đa nền tảng.


2
Các thư viện dành riêng cho nền tảng, các phần mở rộng trình biên dịch không chuẩn, bất kỳ sự phụ thuộc nào vào cách các bit thực sự được đặt trong bộ nhớ và bất kỳ dạng hành vi không xác định / không xác định nào khác là những lý do điển hình mà tôi biết về việc mã trở thành cụ thể của nền tảng. Nếu bạn tránh tất cả điều đó, có, C ++ là khá di động theo mặc định.
Ixrec

"Một chương trình có thể được tạo ra đa nền tảng trong C ++ chỉ bằng cách sử dụng các thư viện đa nền tảng?" Điều này chủ yếu là đúng. Bạn cũng cần phải biên dịch (tạo các nhị phân) cho mỗi nền tảng vì mã máy được biên dịch là dành riêng cho kiến ​​trúc.
rwong

1
Bạn có thể sử dụng khung Qt hoặc POCO .
Basile Starynkevitch

Câu trả lời:


6

Có một ranh giới rất rõ ràng giữa cát giữa nền tảng chéo và nền tảng đơn sắc:

Có phải một chương trình chỉ sử dụng những API được Thư viện chuẩn trưng ra mà nó được xây dựng không?

Nếu bạn nhắm mục tiêu thực hiện tiêu chuẩn, thì bất kỳ nền tảng nào thực hiện tiêu chuẩn đó, theo lý thuyết, sẽ biên dịch và chạy chương trình của bạn một cách chính xác. Có rất nhiều trường hợp ngoại lệ, nhưng nói chung nếu bạn tránh các thủ thuật thông minh, bạn sẽ có thể tránh được nhiều ngoại lệ đó.

Lý do tại sao vấn đề này xuất hiện cụ thể với C ++ là vì trong thời gian dài nhất Thư viện chuẩn C ++ không bao gồm nhiều mô-đun hữu ích cho các chương trình không tầm thường. Đồng thời và GUI là hai cái lớn. Điều này có nghĩa là một chương trình được xây dựng chỉ sử dụng Thư viện chuẩn C ++ không thể có nhiều tính năng mà chúng tôi mong đợi từ phần mềm hiện đại.

Làm cách nào để chúng tôi viết phần mềm đa nền tảng, thứ mà Thư viện Chuẩn không hỗ trợ?

Bạn đề cập đến "thư viện đa nền tảng", trong thực tế thường được gọi là "khung" hoặc "bộ công cụ" dựa trên phạm vi của chúng. Cách để viết phần mềm trong C ++ là đa nền tảng là nhắm mục tiêu không chỉ Thư viện chuẩn, mà là một khung xây dựng trên nền tảng mục tiêu của bạn.

Về cơ bản, bạn kết thúc việc đưa các bit dành riêng cho nền tảng sang một thư viện khác. Ví dụ, wxWidgets là một khung phổ biến. Bạn có thể sử dụng các lớp của nó để xây dựng GUI và chức năng liên quan (ví dụ: hộp thoại tiêu chuẩn để chọn tệp). Dưới vỏ bọc, nó sử dụng biên dịch có điều kiện để thực hiện GUI bằng GUI gốc cho mỗi nền tảng. Nhưng là người sử dụng thư viện, không ai trong số đó quan trọng với bạn.


Lưu ý lịch sử: ở đây vào năm 2015, trình biên dịch và thư viện C ++, phần lớn, thực sự tốt. Quay trở lại một vài năm, và đó không phải là sự thật. C ++ không có tiêu chuẩn chính thức cho đến năm 1998, nhiều năm sau khi ra đời. Các nhà cung cấp phải mất một thời gian dài để cập nhật trình biên dịch và thư viện của họ để thực hiện tiêu chuẩn một cách chính xác. Phần mở rộng dành riêng cho nhà cung cấp có rất nhiều (và thực tế vẫn còn ở đây). Một số trình biên dịch có các tiêu đề và chức năng không chuẩn. Mã di động hầu như không có. Danh tiếng của C ++ về tính di động vẫn còn bị ảnh hưởng.


5

Ở mức độ phức tạp nào thì nền tảng bắt đầu có vấn đề và chương trình sẽ không chạy ở bất cứ đâu?

Về cơ bản bất cứ điều gì không tầm thường. Nếu bạn viết một chương trình không tầm thường, bạn sẽ vô tình phụ thuộc vào một cách cụ thể của trình biên dịch mà nó yêu cầu quá tải, tìm kiếm tên và những thứ phức tạp khác. Hơn nữa, thực tế tất cả các chương trình không tầm thường đều phụ thuộc vào hành vi cụ thể của nền tảng phi Tiêu chuẩn vì Tiêu chuẩn không thực sự cung cấp bất cứ thứ gì ngoại trừ một vài container.

Tuy nhiên, các chương trình không tầm thường có thể khác nhau rất nhiều về việc chúng dễ dàng chuyển sang nền tảng khác như thế nào. Nếu bạn đã lập trình tốt và tuân thủ các quy tắc, bạn có thể chuyển khá dễ dàng và thưởng nếu bạn có thể trừu tượng các phần vào thư viện (có thể đã được cung cấp cho bạn, ví dụ Boost.Filesystem).

Các chương trình hầu như chỉ trở nên rất khó chuyển giữa các nền tảng nếu chúng thực hiện các nhiệm vụ vốn là đặc thù của nền tảng, ví dụ, ghi dữ liệu vào đĩa với các đảm bảo tính nguyên tử / nhất quán hoặc, nếu bạn là một kẻ ngốc và đi khắp nơi làm những việc ngu ngốc không bao giờ những gì bạn nên làm ở nơi đầu tiên, như đúc giữa ints và con trỏ.


2
Chắc chắn điều này nói quá? Tôi biết rằng nhiều mã C ++ bí truyền hơn có thể gặp phải các lỗi trình biên dịch khác nhau trong các trình biên dịch cũ hơn hoặc chất lượng thấp hơn, nhưng bất kỳ trình biên dịch tuân thủ tiêu chuẩn hợp lý nào cũng sẽ xử lý những thứ như quá tải và tra cứu tên giống nhau. Thư viện Chuẩn cung cấp luồng I / O và luồng (bắt đầu bằng C ++ 11) và hỗ trợ hệ thống tệp đang được chuẩn hóa.
Josh Kelley

@JoshKelley: Điều đó về cơ bản không là gì so với những gì hầu hết các chương trình yêu cầu. Ngoài ra, một số trình biên dịch rất phổ biến như MSVC thực hiện quá tải, SFINAE và tra cứu tên khác nhau với các kết quả quan sát khác nhau.
DeadMG

1

Nói một cách rất đơn giản, điều làm nên một nền tảng đa chương trình là khả năng của bạn để lấy các nguồn từ một môi trường, biên dịch chúng trong một môi trường khác và để sản phẩm hoàn thành hoạt động như mong đợi.

Nói một cách đơn giản hơn, nó có sự chồng chéo hoàn toàn giữa những gì chương trình dự kiến ​​sẽ có sẵn và những gì môi trường mục tiêu của bạn cung cấp. Khi bạn thực hiện bất kỳ thao tác nào trùng lặp dưới 100%, chẳng hạn như sử dụng thư viện dành riêng cho môi trường hoặc tính năng ngôn ngữ với hành vi không xác định, bạn đã gắn chương trình của mình với (các) môi trường có thể cung cấp các tính năng không chồng lấp.

("Nền tảng" là một từ hơi khó hiểu. Mọi người có thể nói về Windows và Unix như các nền tảng hoặc Linux, OS X, BSD và Solaris như các nền tảng mặc dù tất cả đều là Unix. kiến trúc phần cứng và mọi thứ trở nên mơ hồ hơn. Đã nói rằng, tôi sẽ bắt đầu sử dụng từ này.)

May mắn thay, có các tiêu chuẩn để giảm bớt vấn đề này:

Ngôn ngữ. Bạn đang viết C ++, lần đầu tiên được ISO chuẩn hóa vào năm 1998. Bất kỳ chương trình nào bạn viết phù hợp với tiêu chuẩn đó đều có thể được biên dịch và chạy với kết quả mong đợi trên bất kỳ nền tảng nào có trình biên dịch và thời gian chạy phù hợp. Không có giới hạn về kích thước hoặc độ tinh vi của chương trình miễn là nó không đi lệch khỏi tiêu chuẩn. Nếu một chương trình có thể đáp ứng tiêu chuẩn không chạy như mong đợi trên một nền tảng nhất định, việc triển khai ngôn ngữ trên nền tảng đó sẽ bị nghi ngờ. Nhiều ngôn ngữ có các bộ kiểm tra được thiết kế cẩn thận có thể được sử dụng để xác minh sự phù hợp.

Java được đề cập đặc biệt bởi vì nó không chỉ chuẩn hóa một ngôn ngữ, mà còn chuẩn hóa mã đối tượng, giúp các chương trình của nó có thể chạy được ở bất cứ đâu mà không cần biên dịch lại. Điều này được thực hiện bằng cách đẩy điểm phù hợp xuống một lớp bổ sung vào một máy ảo tùy chỉnh nền tảng (hoặc thậm chí phần cứng) có khả năng chạy mã đối tượng.

API. Các cuộc gọi bạn thực hiện để chương trình của bạn thực hiện một số điều nhất định cũng có thể được tiêu chuẩn hóa. Giống như các ngôn ngữ, các API và thư viện triển khai chúng có thể được thiết lập để hoạt động như người gọi mong đợi bằng cách sử dụng triển khai cơ bản phù hợp với một nền tảng cụ thể. Một API như vậy là các tiêu chuẩn POSIX của IEEE , phát sinh như một cách để ngăn chặn sự phân mảnh đang xảy ra trong Unix trong những năm 1980. (Lúc đó tôi đang ở đó; khía cạnh của nó không vui chút nào quá khứ. POSIX đã được áp dụng rộng rãi và vẫn được sử dụng rộng rãi gần 30 năm sau.

Tôi đã thực hiện rất nhiều dự án tuân thủ các tiêu chuẩn vì tôi biết chúng sẽ phải chạy trên nhiều nền tảng. Những gì tôi nhận được cho những rắc rối của mình là mã hoạt động ở mọi nơi tôi dự định chạy nó và làm tôi ngạc nhiên về một số nơi tôi không có.


0

Về cơ bản, khi bạn 'chạm' những thứ bên ngoài chương trình của bạn. Một trường hợp cụ thể (tôi không dám nói trường hợp duy nhất) là khi bạn sử dụng các thư viện liên quan đến hệ điều hành. Những thứ như sử dụng bộ nhớ dùng chung giữa quá trình và in những thứ lạ mắt trên bàn điều khiển. Trong trường hợp đầu tiên bạn truy cập vào một phần bộ nhớ được xử lý bởi hệ điều hành, trong trường hợp thứ hai, màn hình cũng được điều khiển bởi hệ điều hành.

Làm GUI phụ thuộc vào HĐH, nhưng có các thư viện GUI được tạo thành đa nền tảng, vì vậy bạn không phải lo lắng về điều đó. Ít nhất là trong lý thuyết.

Rất khó để biến bất cứ thứ gì không tầm thường thành đa nền tảng. Điểm mới là nếu bạn sử dụng đúng thư viện và thực hiện kiểm tra đúng cách thì không khó để làm cho phần mềm có thể mang theo được, ít nhất là nếu mã không quá lớn. Lớn như thế nào là quá lớn phụ thuộc vào quy mô nhóm của bạn, chuyên môn lập trình, v.v.

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.