C ++ không phù hợp với OOP? [đóng cửa]


12

Tôi đã đọc ở đâu đó trong một trong những câu trả lời cho một câu hỏi ở đây (không thể nhớ đó) rằng C ++ không phù hợp với lập trình hướng đối tượng. Có một số đề cập rằng bạn có thể sử dụng tính năng của nó hoặc một cái gì đó tương tự, nhưng không phải theo nghĩa OOP thuần túy (tôi thực sự không hiểu ý của người đó).

Có một số sự thật trong điều này; nếu vậy thì tại sao?



5
OOP không phải là một thuật ngữ được xác định rõ ràng, vì vậy thảo luận về việc C ++ có hay không phù hợp là khá vô nghĩa.
zvrba

Câu trả lời:


31

Như được mô tả tại Vậy điều gì * đã làm * Alan Kay thực sự có nghĩa là thuật ngữ "hướng đối tượng"? , Alan Kay nghĩ rằng việc truyền tin nhắn là phần quan trọng của OOP, nhưng đó là phần "C với các lớp" (sau này trở thành C ++) thiếu. C ++ chỉ là một cấu trúc với một chút hành vi, trong khi các đối tượng trong Smalltalk hoặc Objective-C "thông minh" ở chỗ họ có thể quyết định những gì họ làm với các tin nhắn họ gửi. Nếu một đối tượng Smalltalk-esque nhận được một tin nhắn mà nó không có triển khai, nó có thể thêm một cách lười biếng, chuyển tiếp tin nhắn đến một đối tượng khác hoặc thực hiện bất kỳ điều gì tùy ý.

Những gì C ++ cung cấp theo cách định hướng đối tượng là virtualcác phương thức và tính đa hình liên quan đến cách các phương thức đó được gọi. Khi trình biên dịch nhìn thấy một kiểu dữ liệu (hoặc class) có các phương thức ảo, nó sẽ xây dựng một vtable với một khe cho mỗi phương thức ảo. Các lớp con triển khai các phương thức ảo sẽ đặt các triển khai của chúng vào các vị trí chính xác, vì vậy mã máy khách chỉ cần biết vị trí trong bảng ảo để tìm mã chạy ở đâu thay vì giải quyết tất cả các hàm cụ thể. Điều này có nghĩa là C ++ thực sự có một dạng nhiều công văn, mặc dù tất cả đều được triển khai trong trình biên dịch và không có khả năng như một hệ thống Smalltalk-esque.

Nếu bạn chuyển tin nhắn làm cơ bản cho OOP, thì trong khi bạn có thể làm điều đó với C ++ thì điều đó không hề dễ dàng. OTOH nếu bạn lấy OOP có nghĩa là liên kết dữ liệu với các hàm hoạt động trên dữ liệu đó, C ++ vẫn ổn.


8
+1 - nhưng tôi luôn nghĩ rằng một cuộc gọi chức năng là một cách hợp lý để truyền tin nhắn bằng mọi cách. Đúng, đó là một nền tảng cấp thấp, thay vì một bản sửa lỗi cấp cao cho mọi thứ - nhưng mẫu đối tượng hoạt động cho thấy rằng có thể xây dựng từ nền tảng đó.
Steve314

6
vì vậy đây không chỉ áp dụng với C ++, nhưng để Java, C #, Object Pascal, vv Và nó kết thúc lên được rằng hệ thống Windows thông điệp API là gì Alan nghĩa là điều quan trọng nhất trong OOP, đặc biệt là cách nó được xử lý bởi Delphi
Trinidad

@trinidad đúng, ngoại trừ C # thực sự hỗ trợ độ phân giải động. Tôi hy vọng thật công bằng khi nói rằng ý tưởng về OOP của chúng tôi đã thay đổi theo thời gian để giải quyết vấn đề thiếu thông điệp. Không có nghi ngờ gì bởi các nhà cung cấp nói rằng công nghệ của họ chắc chắn là OOP khi đối mặt với bằng chứng ...

@ steve314 đúng rồi. Thật vậy, đó là cách ObjC hoạt động, một tin nhắn gửi được dịch thành một lệnh gọi tìm kiếm và gọi hàm phương thức. Theo tôi hiểu việc truyền tin nhắn, đó là công văn kép rất quan trọng.

1
@Paul: Có một số kinh nghiệm hạn chế với API Win32, tôi không hiểu. Bất kỳ API nào có các đối tượng có kích thước thay đổi và trước tiên cần gọi một thói quen để xác định đối tượng sẽ lớn như thế nào, phân bổ bộ nhớ và gọi lại, thất bại trong thử nghiệm làm đẹp của tôi.
David Thornley

26

Kiểu thảo luận này làm phiền tôi vì nó nghe có vẻ như là lời giải thích, mọi người tranh luận về ý nghĩa của Holy Scriptute, hay Hiến pháp Mỹ, và ý nghĩa của tác giả ban đầu, như thể những gì chúng ta nghĩ không quan trọng.

Hãy nhìn xem, Alan Kay là một chàng trai thông minh, và anh ta có một ý tưởng hay, đã cọ xát với một loạt các ý tưởng hay khác, và tìm thấy sự hiện thực hóa trong Smalltalk và các ngôn ngữ khác.

Anh ta không phải là Đấng cứu thế và OOP không phải là mô hình lập trình thực sự.

Đó là một ý tưởng tốt, trong số nhiều người. C ++ có ý tưởng hay trong đó, xuất phát từ tư duy OOP không? Tất nhiên là thế.


8

C ++ hỗ trợ OOP, nếu bạn định nghĩa OOP có nghĩa là đóng gói, kế thừa và đa hình.

Tuy nhiên, C ++ không thực sự nổi trội ở OOP. Một lý do là tính đa hình thường phụ thuộc vào các đối tượng phân bổ heap, (mặc dù sử dụng con trỏ thông minh), sẽ tự nhiên hơn khi làm việc với ngôn ngữ được thu gom rác.

Tuy nhiên, trong đó C ++ vượt trội là trong lập trình chung. C ++ cho phép bạn dễ dàng tạo mã chung, hiệu quả cao thông qua các kỹ thuật lập trình chức năng dựa trên mẫu.


4

C ++ mượn các tính năng OOP từ Simula. Một hoặc nhiều nhà phát triển Simula IIRC đã nhận xét rằng C ++ không phải là những gì họ có trong tâm trí.

C ++ có các công cụ trừu tượng tốt, nhưng nó là ngôn ngữ hỗn hợp hơn là ngôn ngữ hướng đối tượng. Các tính năng hướng đối tượng là có, nhưng bạn có các lựa chọn không phải là "OOP nghiêm ngặt".

Một trong những "từ chối" nghịch ngợm mà bạn có trong C ++ là sử dụng sớm hơn là ràng buộc muộn cho các phương thức. Điều này không chỉ khả thi - đó là mặc định. Trong Java, "cuối cùng" có liên quan, nhưng sạch hơn theo một số cách (nó chỉ định ý định theo cách không chỉ là tránh chi phí hiệu năng tầm thường) và đó không phải là mặc định.

Theo một số cách, C ++ cho thấy dấu hiệu là một thử nghiệm ban đầu vẫn còn ở đây. Mặc dù vậy, nó vẫn là một công cụ tốt, với rất nhiều lợi thế mà bạn không có được bằng các ngôn ngữ OOP khác.


2
C ++ cho phép không phải OOP và C ++ cho phép OOP, đối với một số ngôn ngữ là OO, nó phải cho phép OOP, do đó C ++ là ngôn ngữ OO.
Trinidad

1
Tôi tin rằng Alan Kay, người nổi tiếng của Smalltalk, nói rằng C ++ không phải là thứ anh ta nghĩ đến khi đặt ra thuật ngữ "hướng đối tượng". Kể từ khi C ++ bắt đầu là "C with Classes", việc ghép các lớp Simula lên C và không bao giờ nghỉ ngơi sạch sẽ, không có gì lạ khi nó trông giống như một thử nghiệm ban đầu.
David Thornley

1
@Trinidad: MỌI ngôn ngữ cho phép OOP. Tôi đã thấy khá nhiều mã OO đẹp ở dạng cũ C. Vâng, thật đau đớn khi xác định tất cả các bảng phương thức ảo bằng tay, nhưng ngôn ngữ rõ ràng cho phép nó.
Jan Hudec

4

Buộc mọi thứ trở thành một phần của một lớp không nhất thiết phải mang lại mã OO tuyệt vời.

Yêu cầu một lập trình viên thủ tục kém để lập trình trong Java và họ có thể sẽ lấy một lớp ở đâu đó, cung cấp cho nó một phương thức chính tĩnh và gắn 1000 dòng mã trong đó. Tôi biết tôi đã nhìn thấy nó.

Java có một câu lệnh chuyển đổi. Tôi đã thấy switch( type ) { case typeA: bundles_of_code; break; case typeB: bundles_of_other_code; break }vv trong cả mã C ++ và Java.

C ++ hỗ trợ nhiều khái niệm OO nhưng tiêu chuẩn của nó không được xác định bởi nó, tuy nhiên tôi đoán rất nhiều phụ thuộc vào mục tiêu của bạn là gì.

Ngữ nghĩa "nghèo" chính trong C ++ là cho phép xây dựng bản sao của các lớp, theo đó một đối tượng truyền tín hiệu sang một lớp khác. Bạn có thể vô hiệu hóa điều này nhưng sau đó bạn không thể trả lại một từ một chức năng. May mắn là điều này được giải quyết trong C ++ 0x.


3

OOP không chỉ là về việc đảm bảo mọi thứ đều hoặc trong một lớp. Hoàn toàn có thể viết mã không OO bằng ngôn ngữ "hoàn toàn OO". Ví dụ, "chính" thường được chỉ ra là một hàm toàn cục, nhưng việc phát minh ra một lớp chỉ để chứa một phương thức chính tĩnh cũng giống như không phải là OO.

C ++ hoạt động tốt nhất với sự pha trộn của nhiều thứ khác nhau; điều này không đáng ngạc nhiên, vì đó là cách tốt nhất làm việc tốt nhất. Thường thì OOP là một trong những công cụ rất hữu ích.


2

C ++ có thể được sử dụng cho OOP nhưng nó không 'thuần' như một thứ gì đó như Smalltalk. C ++ cũng cho phép bạn thực hiện phi OOP, đó là những gì mọi người có thể nói về.


2

Mặc dù tôi không đồng ý với tình cảm này, nhưng sự thật là hệ thống loại của C ++ không phải là OOP thuần túy - không phải "mọi thứ đều là một đối tượng". Các số (đặc biệt) không thể được mở rộng dễ dàng như họ có thể nói, Smalltalk. Bạn không thể xác định lại ý nghĩa của "2 + 2" (mặc dù bạn có thể xác định lại ý nghĩa của "hai + hai").

Nhưng điều mà hầu hết mọi người có thể muốn nói là nhiều người viết mã không hướng đối tượng trong C ++ nhưng tin rằng vì họ đang sử dụng ngôn ngữ "OOP", nên họ hướng đối tượng. Đo không phải sự thật. Nhưng theo tôi, bạn có thể viết mã mệnh lệnh gớm ghiếc trong Smalltalk và không vượt trội so với thiết kế OOP đàng hoàng trong C ++.


1

Sự phản đối hoàn toàn hợp lệ của Alan Kay đối với C ++ là đó là ngôn ngữ vĩ mô trên C.

Khái niệm "truyền thông điệp" chỉ đơn giản là ý tưởng rằng các thể hiện của các lớp được lưu giữ trong bộ nhớ và chúng phơi bày các phương thức có thể được gọi. Truyền tin nhắn được * mô phỏng "trong C ++ bằng cách sử dụng vtables giữ các con trỏ tới các hàm.

Để nói rằng việc truyền tin nhắn không tồn tại trong C ++ là không chính xác, điều chính xác hơn để nói là việc truyền tin nhắn là một phần không thể thiếu của các ngôn ngữ khác như smalltalk và Java vì ngôn ngữ này không xử lý trực tiếp cấu trúc nước ngoài và ghép nó trực tiếp lên C.

Đây là một đối số thiết kế ngôn ngữ có ngữ nghĩa cao mà tôi nghi ngờ là hơi vượt quá mức kinh nghiệm của người hỏi.

Điều đó đang được nói có hàng ngàn lý do để ghét C ++, và rất ít lý do để yêu thích nó.

Thay vì tìm kiếm chiếc búa hoàn hảo và bộ móng hoàn hảo, hãy tìm ngôi nhà hoàn hảo để xây dựng và sau đó tìm công cụ phù hợp ... cần có kinh nghiệm.

Điều quan trọng cần nhớ là trong lập trình hệ thống, điều mà Alan Kay lo ngại không phải là "OOP thuần túy" thực sự là một thế mạnh của C ++. Để mỗi ...


1
Mục tiêu C cũng bắt đầu như ngôn ngữ macro trên đầu C, nhưng là ngôn ngữ hướng đối tượng.
Jan Hudec

1

Theo quan điểm của tôi, nó không phải là một vấn đề xác định như là một vấn đề khả năng sử dụng.

Các đối tượng là một sự trừu tượng nhằm làm cho nó dễ đọc, viết và lý do về các chương trình phức tạp. Đối với một lập trình viên thực tế, liệu một ngôn ngữ có đáp ứng tất cả các tiêu chí của một định nghĩa chính thức cụ thể về "hướng đối tượng" (dường như có một số đối thủ cạnh tranh!) Không thực sự quan trọng như việc các công cụ mà nó cung cấp có phù hợp để suy nghĩ về chương trình của bạn về các đối tượng đã nói - nghĩa là, thực sự gặt hái những lợi ích năng suất được cho là của OOP.

Trong C ++, các đối tượng là một sự trừu tượng bị rò rỉ khủng khiếp , thường buộc các lập trình viên phải vật lộn với các vấn đề khó chịu liên quan đến cách các đối tượng đó được cấu trúc trong bộ nhớ - các vấn đề gợi nhớ đến mã hóa C thẳng hơn các ngôn ngữ OOP khác. Ví dụ: Câu trả lời thường gặp của C ++ đưa ra lời chỉ trích này (trong số những câu hỏi khác):

Sẽ rất có lợi cho một học viên làm quen với các hệ thống OO khác với C ++ và với các định nghĩa OO khác với bộ ba "đóng gói, kế thừa, đa hình" được diễn giải theo những cách đặc biệt cho phép C ++ được coi là "OO". Ví dụ, một tuyên bố rằng một môi trường thiếu kiểm tra ranh giới hoặc thu gom rác không phải là môi trường OO nghe có vẻ thái quá đối với những người quen với C ++. Nhưng từ nhiều góc độ, nó có rất nhiều ý nghĩa. Nếu bất cứ ai cũng có thể ghi đè lên một đối tượng, thì "đóng gói" ở đâu? Nếu việc xử lý một đối tượng có thể dẫn đến các tham chiếu lơ lửng hoặc rò rỉ bộ nhớ, thì hệ thống "hướng đối tượng" như thế nào ? Còn khả năng cho biết loại vật thể nào được đặt tại một địa điểm và thời gian nhất định? Bạn nói phần mềm hoạt động với các đối tượng - chúng ở đâu? Và nếu không thể tìm ra, làm thế nào để gỡ lỗi phần mềm?

C ++ là hướng đối tượng, nhưng không thoải mái và không đầy đủ: người dùng của nó phải dành rất nhiều nỗ lực để đảm bảo dữ liệu của họ thực sự hoạt động như các đối tượng "thực" chứ không phải là các bit sai lầm. Điều đó nói rằng, rất nhiều mã đã được viết bằng C ++ trong suốt tuổi thọ của nó, hầu hết mã này sử dụng các lớp và công văn động, do đó, nó rõ ràng là thứ mà bạn có thể sử dụng cho OOP thực tế.


-1 để tham khảo FQA trong câu trả lời nghiêm túc. FQA là một tổ của những biến dạng, nửa sự thật và hiểu lầm.
David Thornley

@DavidThornley Là trích dẫn cụ thể là một sự xuyên tạc, nửa sự thật hoặc hiểu lầm?
Alex P

Một nơi nào đó trong đó. Khiếu nại rằng ngôn ngữ OO phải được kiểm tra ranh giới (đôi khi được tích hợp vào các thùng chứa tiêu chuẩn C ++) và bộ sưu tập rác (con trỏ thông minh là bộ sưu tập rác nguyên thủy) bị ép buộc và không rõ ràng. Câu về một ngôn ngữ cho phép các tham chiếu lơ lửng không hướng đối tượng rõ ràng là Bằng chứng xác nhận trắng trợn. Tôi bối rối trước "khả năng nói loại vật nào"; loại con trỏ cung cấp cho các đối tượng không có hành vi ảo và RTTI xử lý nó cho các đối tượng có hành vi ảo.
David Thornley

@DavidThornley Yêu cầu của FQA là ngôn ngữ OO hữu ích cần có những điều này - phù hợp với câu hỏi đang được hỏi (C ++ có "phù hợp" không?). Tôi nghĩ rằng một tuyên bố về các định nghĩa xương trần thực sự không giải quyết được rằng ... "Khả năng nói": một hành vi lỗi phổ biến truy cập vào một đối tượng không thực sự ở đó, bằng cách theo một con trỏ đến một số dữ liệu chưa được ghi đè hoặc bị ghi đè trước đó; và chương trình của bạn sẽ vui vẻ lấy rác đó và giải thích nó thành dữ liệu, sau đó theo con trỏ rác đến dữ liệu rác khác cho đến khi nó chạm vào địa chỉ ngoài giới hạn hoặc xảy ra một số lỗi lớn.
Alex P

Tuy nhiên, trích dẫn ít nhất đề nghị mạnh mẽ tuyên bố rằng một ngôn ngữ không có kiểm tra ranh giới hoặc bộ sưu tập rác không phải là OO và bỏ qua thực tế là bạn có những thứ đó trong C ++ nếu bạn muốn. Câu hỏi liệu một ngôn ngữ có ngăn ngừa một số loại lỗi nhất định hay không (vì bất kỳ lý do gì) là trực giao cho dù đó là OO.
David Thornley

-1

Có một lý do Graham Lee đã có nhiều sự ủng hộ nhất ở đây. Để nhắc lại, có vẻ như một lớp C ++ không thực sự là một đối tượng theo nghĩa là nó không thực hiện truyền thông điệp. Tôi nghĩ rằng đây là những gì khiến mọi người đi lên rất nhiều khi họ đang học C ++ hoặc oop. Mọi người được bảo hướng đối tượng là 'cái này' và sau đó nói rằng C ++ thực hiện nó khác đi. Vâng C ++ không bao giờ làm OOP khác nhau. Nếu bạn nghĩ theo cách này, bạn sẽ không bao giờ đánh giá cao các lớp C ++ vì ý nghĩa của chúng và đó chỉ là sự cải thiện mô hình thủ tục bằng cách kết hợp trừu tượng hóa và hành vi năng động. Vì vậy, các lớp C ++ là thủ tục cơ bản, chúng chỉ cải thiện mô hình thủ tục, hay đúng hơn là chúng là phiên bản nâng cao hơn của cấu trúc C.


Bạn có bất kỳ lý do hỗ trợ thực tế cho lập luận của bạn? Bạn dường như đang đưa ra những khẳng định và cho rằng những người không đồng ý phải bị nhầm lẫn, hoặc sẽ thay đổi suy nghĩ nếu họ nhìn nó khác đi, hoặc có lẽ nếu họ chia sẻ định nghĩa chính xác về OO của bạn.
David Thornley

Đủ công bằng. Bạn có thể đọc bài viết này . Tôi đoán những gì tôi đã nói là c ++ không phải là "lập trình hướng đối tượng" theo nghĩa chặt chẽ của Alan Kay. Tuy nhiên nếu bạn định nghĩa OOP là cấu trúc dữ liệu với hành vi thì bạn có thể coi c ++ là OOP. Trong suy nghĩ của tôi, mặc dù chính xác hơn khi xem một lớp c ++ như một sự trừu tượng hóa lập trình thủ tục ở cấp độ cao hơn. Một lớp c ++ hiệu quả hơn nhiều so với một đối tượng kiểu Kay, nhưng tệ hơn cho sự tương tranh. Cá nhân tôi nghĩ rằng lớp c ++ là một thiết kế tuyệt vời.
annoying_squid

1
Cảm ơn vì liên kết, nhưng nó chỉ giải thích ý nghĩa của Alan Kay. Hơn nữa, tôi không đồng ý rằng Smalltalk thường được coi là ngôn ngữ OO đầu tiên và Wikipedia đồng ý với tôi rằng đó là Simula, một trong hai ngôn ngữ Stroustrup kết hợp để tạo thành C với Classes. Tôi quan tâm đến tuyên bố của bạn rằng một lớp C ++ là một sự trừu tượng hóa lập trình thủ tục ở cấp độ cao hơn so với một mẫu đối tượng, nhưng tôi vẫn không hiểu tại sao bạn nghĩ như vậy.
David Thornley

Định hướng đối tượng có lẽ là một thuật ngữ chủ quan, nếu chúng ta có thể đồng ý về điều đó. Nhưng tôi thấy một đối tượng Kay như một cách tự nhiên hơn để tách mã và giới thiệu tính mô đun đồng thời theo nghĩa mỗi đối tượng phục vụ một vai trò giống như các máy tính mini tương tác thông qua tin nhắn. Trong mô hình này, cần có ít hoặc không có mã 'ở giữa' b / c, toàn bộ logic của chương trình có thể được biểu thị dưới dạng ô và thông báo. Bằng cách so sánh, việc sử dụng 'lớp' thường yêu cầu một số mã keo thủ tục ở giữa (thiếu tính mô đun thực sự) nhưng lợi thế là các lớp hiệu quả hơn nhiều.
annoying_squid

-1

Steve Yegge nói điều đó tốt nhất :

C ++ là ngôn ngữ ngu ngốc nhất trên trái đất, theo nghĩa rất thực tế là ít có tình cảm nhất. Nó không biết về chính nó.

Hệ thống đối tượng trong C ++ rất cứng và cố định vào thời gian biên dịch, nó rất khác với khái niệm ban đầu về OOP liên quan đến việc truyền thông điệp, hướng nội, phản xạ, gửi động và ràng buộc muộn, trong số những thứ khác. Điểm chung duy nhất của C ++ và Smalltalk là một chút từ vựng.


C ++ là ngôn ngữ ít cảm tính nhất? Một ngôn ngữ có nghĩa là gì? Nếu bạn có nghĩa là nó thiếu khả năng phản chiếu, điều đó khá phổ biến và chắc chắn không chọn C ++ ra khỏi đám đông.
David Thornley

2
Làm thế nào trên trái đất bạn có thể nói rằng ông nói nó "tốt nhất"? Tôi không biết ý nghĩa của trích dẫn ngẫu nhiên đó là gì.
dùng16764

+1 nói rằng loại điều này sẽ nhận được rất nhiều từ các bashers cơ bản của C ++, nhưng phải nói rằng - bạn không thể thực sự OOP mà không có sự phản chiếu, bởi vì bạn không có sự tổng quát để quan tâm đến các công cụ ngang ( các khía cạnh) - vòng đời (kích hoạt, xử lý), xử lý lỗi chung, ủy quyền chung, tuần tự hóa chung, song song nhiệm vụ chung - những điều này cuối cùng gây ô nhiễm mã của bạn và phá vỡ SoC.
vski

Cảm ơn. Tôi không thể tin rằng tôi đã đến -3 khi nói rằng một ngôn ngữ không có sự phản chiếu không phải là một ví dụ hay về OOP.
John Cromartie

1
@JohnCromartie, bạn có thể giải thích về điểm đó trong câu trả lời của bạn không?
Jeremy Heiler
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.