2010-02-05 40 views
14

tôi có lớp học với rất nhiều chức năng chuyển đổi:Tôi có thể cấm gọi các phương thức tĩnh trên cá thể đối tượng không?

class Something { 
    public: 

    string toXml(); 
    string toJson(); 
    ... 

    static Something fromXml(string); // factory 
    static Something fromJson(string); // factory 
    ... 
}; 

Bởi vì chức năng tĩnh có thể được gọi vào dụ, nó rất dễ dàng để viết mã như thế này:

Something sss; 

... initializing sss ... 

string xml1 = sss.toXml(); 
sss.fromXml(xml1); // does nothing 
string xml2 = sss.toXml(); 
assert(xml1 == xml2); // always true 

Vì vậy, tôi muốn cấm gọi từXXX trên các đối tượng hoặc ít nhất khiến chúng làm điều gì đó khác biệt.

Có cách nào để thực hiện việc này không?

+0

Không nên trình biên dịch cảnh báo nếu một hàm tĩnh đang được gọi trên một đối tượng? Depedning trên môi trường của bạn, có lẽ bạn có thể thêm #pragma hoặc cờ trình biên dịch để buộc cảnh báo đó là một lỗi? – Macke

+0

@Marcus: Đó là hợp lệ C++. Nếu tôi có thể buộc cảnh báo về điều này, nó sẽ là đủ cho tôi. Nhưng có vẻ như không thể. – Ivan

Trả lời

0

Sửa đổi thiết kế của bạn để thay thế. Chia các phương thức tĩnh của bạn thành một lớp SomethingFactory riêng biệt. Điều này chỉ là khó hiểu.

+0

Đó cũng có thể là không gian tên SomethingFactory. Nhưng sau đó các chức năng phải là bạn với lớp Something. Mã sẽ phức tạp hơn. Nếu tôi có thể cấm cú pháp cuộc gọi khó hiểu, nó sẽ hoàn toàn OK. – Ivan

+0

@Ivan: Nếu bạn có thể thiết kế lại ngôn ngữ C++ để vấn đề cụ thể của bạn là tầm thường, thì bạn không còn gặp bất kỳ vấn đề gì nữa. (Và đó là đôi khi là giải pháp tốt nhất.) Tuy nhiên, nó không thể chuyển đổi ngôn ngữ đáp ứng yêu cầu của bạn và vì vậy giải pháp lý tưởng của bạn chỉ là không thể trong C + +. –

+0

@Roger: Tôi không chắc chắn tiêu chuẩn C++ trực tiếp nói rằng tôi không thể xác định biểu mẫu cuộc gọi nào đã được sử dụng. Nếu C++ đánh giá "đối tượng" trong "object.staticMethod()", thì nó có thể cung cấp nó cho hàm tĩnh là "this". Hoặc làm một cái gì đó như nó. – Ivan

5

Họ có thực sự cần phải là thành viên của lớp học không? Cách rõ ràng để ngăn chặn điều này là làm cho chúng hoạt động miễn phí.

+4

Trên ghi chú đó: http://www.drdobbs.com/cpp/184401197 Nói về cách các chức năng miễn phí tốt hơn cho việc đóng gói. – Eld

+0

Tôi chỉ muốn giữ sạch không gian tên toàn cầu - đối tượng này có thể nhìn thấy mọi thứ trong chương trình lớn. Tất nhiên tôi có thể tạo không gian tên "SomethingUtils" cho họ. Nhưng chúng trông giống như các chức năng "nhà máy". Nó thực sự có ý nghĩa cho đến khi tôi lãng phí 2 giờ tìm kiếm "lỗi" không tồn tại. – Ivan

+0

Eld, chức năng miễn phí sẽ là "bạn bè" với lớp học anyway. Mức độ đóng gói không thay đổi. – Ivan

3

Các tiêu chuẩn thực sự đòi hỏi tất cả các trình biên dịch phù hợp để cho phép điều đó cú pháp trong 9.4 [class.static]/2:

Một thành viên tĩnh của lớp X chưa gọi sử dụng biểu thức có trình độ-id X :: s; không cần thiết để sử dụng cú pháp truy cập thành viên của lớp (5.2.5) để chỉ một thành viên tĩnh. Thành viên tĩnh có thể được giới thiệu bằng cách sử dụng cú pháp truy cập thành viên của lớp , trong trường hợp biểu thức đối tượng là được đánh giá.

Giờ đây, có một số điều bạn có thể làm để tránh những cạm bẫy, không theo thứ tự đặc biệt

  • Chuyển đổi chúng thành miễn phí chức năng không cho phép cú pháp
  • Cải thiện quy ước đặt tên: createFromXml để làm rõ ràng hơn rằng đó là phương pháp nhà máy
  • Chuyển đổi phương thức tĩnh thành phương pháp cụ thể sẽ thực hiện thao tác trong đối tượng và cung cấp một nhà máy phương thức bên ngoài sẽ sử dụng lại mã.

Từ quan điểm thiết kế, tùy chọn đầu tiên có lợi thế là bỏ ghép các định dạng được tuần tự hóa khỏi chính lớp đó. Something (bởi một tên tốt hơn), đại diện cho một đối tượng với các thuộc tính và hoạt động và tất cả những thứ OO đó. Nhưng trong nhiều trường hợp, Something không liên quan đến việc nó có thể được tuần tự hóa để gửi hoặc lưu trữ ở các định dạng khác nhau.

Người dùng lớp học Something chỉ muốn làm việc với XML của bạn không cần phải biết rằng đối tượng của bạn có thể được tuần tự hóa thành Json. Cả người dùng Json hoặc XML đều không bị ảnh hưởng nếu sau này bạn thêm tùy chọn kiên trì cơ sở dữ liệu vào lớp.

+0

@David: các chức năng này không dành cho serialization, nhưng để chuyển đổi. Bất kỳ ai sử dụng tiêu đề đó sẽ muốn chuyển đổi thứ gì đó thành biểu mẫu hữu ích hơn. Nó có thể là JSON, XML hoặc đối tượng khác. Giữ tất cả các công cụ này trong một tiêu đề có vẻ hợp lý. Vì vậy, tiêu chuẩn cho phép cả hai biểu mẫu cuộc gọi. Nhưng nó không nói rằng tôi không thể xác định hình thức đã được sử dụng. Ví dụ, nó có thể thiết lập "this" thành NULL trong "Type :: method" gọi, nhưng đối tượng thực trong "object.method" gọi. Tuy nhiên, tôi tự hỏi tại sao cú pháp "object.method" được phép ở tất cả. Nó là khó hiểu, đặc biệt là trong "this-> staticMethod()" hình thức đó là cần thiết trong các mẫu. – Ivan

+0

'this->' hiếm khi được yêu cầu, ngay cả trong các mẫu. Nó đôi khi thuận tiện hơn khi sử dụng một tên đủ điều kiện ('Name :: member'), chẳng hạn như khi truy cập vào một thành viên được thừa kế từ một lớp cơ sở, phụ thuộc vào tham số mẫu (và do đó thành viên là một tên phụ thuộc. chỉ cần đặt tên nó một mình). –

+0

@Roger: Đó là cú pháp khác. Tên đủ điều kiện sẽ phá vỡ nếu bạn đổi tên lớp hoặc di chuyển nó sang không gian tên khác và "this->" sẽ không. Và dù sao cũng khó hiểu. Tại sao C++ cho phép cú pháp "object.staticMethod()"? Bạn có thể sử dụng "Type :: staticMethod()" thay vào đó với hàm trợ giúp mẫu nhỏ. – Ivan

-1

Làm cách nào để đặt thành viên tĩnh của bạn ở chế độ riêng tư?

Nếu bạn cần có các hàm thành viên tĩnh, đây có thể là cách để giải quyết vấn đề này.

Tại sao bạn có chức năng thành viên tĩnh? Họ có cần quyền truy cập vào thứ khác trong lớp không?Nếu không, sau đó bạn có thể làm cho họ chức năng miễn phí mà không có trong tiêu đề với Something, nhưng trong một tiêu đề trong một không gian tên riêng biệt.

+0

Riêng tư sẽ không hoạt động ở đây và thực sự không liên quan gì đến nó. Chúng là các phương thức của nhà máy, đó là một cách khác để nói chúng là các nhà xây dựng đặc biệt ("các nhà xây dựng có tên"). –

+0

Lớp này chỉ có các hàmXXX/từXXX và con trỏ để triển khai. Di chuyển các chức năng ra ngoài sẽ làm cho lớp này gần như trống rỗng. Và họ vẫn phải là bạn. Không có các chức năng này Một điều hoàn toàn vô dụng. Tôi không nghĩ rằng họ nên ở trong tập tin tiêu đề riêng biệt. – Ivan

Các vấn đề liên quan