2009-05-12 43 views
12

Tôi đã làm việc nhiều năm với Java. Trong những năm đó, tôi đã sử dụng sự phản chiếu rộng rãi (hoặc có thể là thường xuyên), và thấy nó hữu ích và thú vị. Nhưng 8 tháng trước, tôi đã thay đổi công việc của mình, và bây giờ Java chỉ là một ký ức, và tôi đang bắt tay vào C++. Vì vậy, bây giờ tôi tự hỏi nếu có bất kỳ cơ chế phản ánh trong C + +. Tôi đã đọc về RTTI nhưng tôi cảm thấy nó không có nghĩa là sức mạnh của sự phản xạ Java (hoặc các ngôn ngữ khác). Tôi đang bắt đầu nghĩ rằng không có cách nào để làm điều này trong C++. Liệu tôi có sai?Phản ánh trong C++

Trả lời

5

Nếu bạn đang tìm kiếm một cách hoàn toàn chung để thao tác đối tượng trong thời gian chạy khi bạn không biết loại của họ tại thời gian biên dịch trong C++, bạn về cơ bản cần phải:

  1. Xác định một giao diện (lớp cơ sở trừu tượng với tất cả các phương thức ảo thuần túy và không có thành viên) cho mỗi khả năng mà một lớp có thể hỗ trợ.
  2. Mỗi lớp phải kế thừa hầu như từ tất cả các giao diện mà nó muốn triển khai (có thể trong số các lớp khác).

Bây giờ, giả sử pFoo giữ một con trỏ giao diện kiểu IFoo* đối với một số đối tượng x (bạn không cần phải biết kiểu dữ liệu cụ x 's). Bạn có thể xem liệu đối tượng này hỗ trợ giao diện IBar bằng cách nói:

if (IBar* pBar = dynamic_cast<IBar*>(pFoo)) { 
    // Do stuff using pBar here 
    pBar->endWorldHunger(); 
} else { 
    // Object doesn't support the interface: degrade gracefully 
    pFoo->grinStupidly(); 
} 

Cách tiếp cận này giả định rằng bạn biết tất cả các giao diện có liên quan tại thời gian biên dịch - nếu bạn không, bạn sẽ không thể sử dụng C++ bình thường cú pháp để gọi các phương thức. Nhưng thật khó để tưởng tượng một tình huống mà chương trình gọi không biết giao diện nó cần - về trường hợp duy nhất tôi có thể nghĩ là nếu bạn muốn phơi bày các đối tượng C++ thông qua trình thông dịch tương tác. Thậm chí sau đó, bạn có thể đưa ra một cách (xấu xí, bảo trì chuyên sâu) để làm điều này thành mô hình trên, để các phương thức có thể được gọi bằng cách xác định tên và đối số của chúng dưới dạng chuỗi.

Khía cạnh khác cần xem xét là tạo đối tượng. Để thực hiện điều này mà không biết các loại cụ thể, bạn sẽ cần một hàm nhà máy, cộng với các định danh duy nhất cho các lớp để chỉ định lớp bê tông nào bạn muốn. Có thể sắp xếp các lớp học để đăng ký bản thân với một nhà máy toàn cầu khi khởi động, as described here by C++ expert Herb Sutter - điều này tránh được việc duy trì một tuyên bố khổng lồ switch, giúp bảo trì đáng kể. Có thể sử dụng một nhà máy duy nhất, mặc dù điều này ngụ ý rằng có một giao diện duy nhất mà mọi đối tượng trong hệ thống của bạn phải triển khai (nhà máy sẽ trả lại một con trỏ hoặc tham chiếu đến loại giao diện này).

Vào cuối ngày, những gì bạn gió lên với là cơ bản (đẳng cấu với) COM-dynamic_cast<IFoo*> hiện công việc giống như QueryInterface(IID_IFoo), và giao diện cơ sở được thực hiện bởi tất cả các đối tượng tương đương với IUnknown.

1

RTTI là một giải pháp (phần nào trong Java bạn nghĩ không có trong RTTI?), Nếu không bạn có thể thực hiện khung đối tượng của riêng bạn - cho phép mọi đối tượng C++ của bạn thừa hưởng một số giao diện phản chiếu.

+1

Tôi nghĩ kiến ​​thức về RTTI của tôi kém ... nhưng có cách nào để lấy danh sách các phương pháp hoặc thuộc tính của một đối tượng bằng RTTI không? – aitor

+2

@aitor: Không, tôi không tin như vậy. RTTI có thể cho bạn biết loại đối tượng trong thời gian chạy, nhưng bạn có trách nhiệm chuyển đổi thông tin này thành thông tin chính xác hơn, chẳng hạn như tính sẵn có của các phương thức và thuộc tính. –

+1

RTTI phức tạp có thể trông giống như sau: http://www.codeproject.com/KB/library/vcf_rtti.aspx – Francis

15

Vì tiêu chuẩn C++ không bao gồm khái niệm như "siêu dữ liệu", không có phương thức di động (qua các trình biên dịch và nền tảng khác nhau) cho phương pháp phản xạ thời gian chạy khác với RTTI bạn đã đề cập.

Trong C++, cũng có khả năng phản ánh thời gian biên dịch (nghĩ boost::type_traitsboost::type_of), nhưng nó cũng bị giới hạn so với Nemerle hoặc LISP.

Hầu hết các khung chính (MFC, Qt, v.v.) cho phép bạn trích xuất các biến dạng trong thời gian chạy, nhưng chúng yêu cầu tất cả các chú thích đặc biệt để nó hoạt động (xem RUNTIME_CLASS et al làm ví dụ).

0

nếu tất cả bạn đang sử dụng nó là tiêm phụ thuộc (triển khai một số giao diện^H^H^H^H^H^lớp trừu tượng thuần túy), bạn có thể thử tải động tệp .dll hoặc .so chứa việc triển khai trong ngày cho bất kỳ plugin nào.

Có lẽ chỉ cần nắm bắt ở ống hút, vì điều này sẽ không hoạt động tốt cho nhiều lần triển khai thực hiện cùng một lúc.

3

Bạn cần sử dụng mẫu khách truy cập. Bất kỳ lớp nào có thể được phản ánh trên sẽ cần phải kế thừa một lớp cơ sở cho nó một hàm thành viên Reflect, sẽ chấp nhận một lớp khách truy cập. Sau đó, chức năng Reflect sẽ chuyển thông tin hoặc khả năng về các thành viên khác cho khách truy cập.

Nhiều thư viện phổ biến sử dụng mẫu này cho các trường hợp cụ thể, ví dụ: chức năng Serialize trong MFC thực hiện điều này nhưng đặc biệt cho tuần tự hóa.

Bạn có thể thiết kế hệ thống theo cách mà khách truy cập có thể thực hiện cuộc gọi năng động đến các chức năng thành viên, nhận hoặc đặt giá trị của thành viên dữ liệu, v.v. một hàm Reflect được viết bằng tay, đó sẽ là sự lặp lại cấu trúc của lớp.

1

Phản ánh là quá trình mà theo đó chương trình máy tính có thể quan sát và sửa đổi cấu trúc và hành vi của riêng nó. Tôi không thấy làm thế nào bạn có thể làm phản ánh trong C + +. RTTI chỉ hữu ích cho kiểu dữ liệu của đối tượng trong bộ nhớ khi chạy.

4

Hãy xem my answer to a similar question. Cả hai giải pháp (XRTTI và OpenC++) được đề xuất dựa trên các công cụ bên ngoài tạo ra siêu dữ liệu phản chiếu cho bạn trong quá trình xây dựng.

0

Bạn cần làm gì trong C++ và bạn đang làm việc với nền tảng nào? Tôi biết một cách để có được các định nghĩa lớp hoàn chỉnh và gọi các hàm sử dụng dữ liệu này, nó hoạt động trong Windows nhưng tôi không biết về các nền tảng khác. Ý tưởng là lấy dữ liệu từ bảng xuất DLL hoặc exe. Nó không phải là dễ dàng - nó đã cho chúng tôi vài tháng làm việc để có được một thực hiện phong nha - nhưng nó sẽ làm tất cả mọi thứ mà các ngôn ngữ hỗ trợ phản ánh làm.

+0

Câu trả lời của bạn có nghĩa là gì? nơi thực hiện phong nha bạn nói về? –