2017-09-18 19 views
16

Có tốt không khi sử dụng trường tham chiếu const làm trình lấy chỉ đọc trong các lớp C++?Trường tham chiếu Const là thuộc tính chỉ đọc trong lớp C++

Ý tôi là, mã này có đáp ứng các phương pháp hay không?

class check{ 
private: 
    int _x; 
public: 
    const int& x = _x; 
    void setX(int v){ 
     _x = v; 
    } 
}; 

Nó đang làm việc rất giống với C# thuộc tính, IMHO, và rất dễ dàng và sạch sẽ trong mã sử dụng lớp:

check s; 
    int i; 
    std::cin >> i; 
    s.setX(i); 
    std::cout << s.x << '\n'; 
    s.setX(7); 
    // s.x = i; // Error 
    std::cout<<s.x<<'\n'; 
+4

Và có thể là const cast to oblivion :) – StoryTeller

+5

Không, nó là một thực tế xấu kể từ khi lưu trữ tham chiếu này có thể gây ra một chi phí bộ nhớ thêm so với một hàm getter nội tuyến đơn giản. Một điều nữa là bạn sẽ không thể thực hiện kiểm tra/kiểm tra thời gian chạy bất kể giá trị được truy cập. Thật không may là không có cách nào thực sự để mô phỏng cú pháp giống như thuộc tính C#. Có một [mở rộng thuộc tính 'đặc trưng của MS] (https://docs.microsoft.com/en-us/cpp/cpp/property-cpp) nhưng chúng không chuẩn và bị bỏ rơi. – VTT

+11

Hãy thử gán một 'kiểm tra' cho một dấu kiểm khác. – molbdnilo

Trả lời

19

làm mã này đáp ứng các thông lệ tốt?

Không thực sự, vì nó giới thiệu sự phức tạp không cần thiết và chi phí không gian.

Hơn nữa, bạn sẽ không thể thực hiện kiểm tra thời gian chạy và/hoặc xác nhận, bất kể giá trị đang được truy cập.

Hơn nữa, điều gì sẽ xảy ra với tuổi thọ và ngữ nghĩa?

Hãy thử chỉ định một check trong mã của bạn cho mã khác và xem điều gì xảy ra. Bài tập được tạo ra không đúng vì lớp học không thể chuyển nhượng được. Bạn nên cung cấp một bản sao và di chuyển constructor để chăm sóc tài liệu tham khảo, do đó nó sẽ không tham chiếu đến thành viên dữ liệu của đối tượng cũ.

Sử dụng tốt hơn _x trực tiếp và có chức năng lấy nội tuyến đơn giản.


PS: C#-like properties in native C++?

+0

'Thử chỉ định một kiểm tra trong mã của bạn cho mã khác và xem điều gì xảy ra. Đối tượng của bạn được sao chép 'Không, không phải. Bài tập được tạo ra không đúng vì lớp học không thể chuyển nhượng được. – user2079303

+0

Vấn đề sao chép chỉ có nghĩa là bạn phải cung cấp các nhà xây dựng sao chép và di chuyển để đảm bảo rằng các điểm tham chiếu vào đối tượng cục bộ. Chuyển nhượng không phải là một vấn đề, vì nó không thể thay đổi một tham chiếu trong một toán tử gán anyway, và một destructor cũng không cần thiết. – cmaster

6

Nói chung, nó là không một thói quen tốt.

imho và rất dễ dàng và sạch sẽ trong mã sử dụng lớp học.

Tại sao điều đó rõ ràng hơn và dễ dàng hơn?

  • Bạn giới thiệu một thành viên khác (chi phí vô dụng). (Nói chung, tham chiếu sẽ được thực hiện như một con trỏ thành viên bổ sung).
  • Điều này làm cho mã khó duy trì hơn. Bạn đang thực sự tạo ra sự phụ thuộc giữa các thành viên biến.
  • Nó gây ra vấn đề trong nhiệm vụ và trong các hoạt động sao chép. Hoạt động sao chép phải hoạt động như thế nào?

Các "cổ điển" cách tiếp cận là âm thanh rõ ràng hơn bởi tôi, ví dụ .:

class Foo { 
public: 
    void set_num(int value) noexcept { m_num = value; } 
    int get_num() const noexcept { return m_num; } 
    void set_string(std::string value) noexcept { 
     m_str = std::move(value); 
    } 
    const std::string& get_string() const noexcept { 
     return m_str; 
    } 
private: 
    int m_num; 
    std::string m_str; 
}; 

Từ một điểm biểu diễn trên, phương pháp này nên được ưa thích.

  • Thời gian phức tạp: gọi get_variable trên một inline chức năng không giới thiệu chi phí hơn "cách tiếp cận tài liệu tham khảo" của bạn. Hơn nữa, nó là rất tối ưu hóa bởi trình biên dịch (vì đơn giản của mã).
  • Mức độ phức tạp của không gian: không giới thiệu thành viên dữ liệu bổ sung.
4

Những gì bạn đề nghị là ở chung một ý tưởng tồi:

  • Bạn không thể thực hiện bất động sản bằng cách thực hiện bất kỳ chế biến (ví dụ với một getter bạn có thể lưu trữ tọa độ sử dụng [x, y] và sau đó quyết định thay đổi việc triển khai để sử dụng [góc, bán kính] trong khi vẫn giữ cùng một giao diện công khai).
  • Sử dụng biến thành viên const liên quan đến chi phí không gian và không cung cấp cho bạn bất kỳ lợi thế hiệu suất nào so với trình thu thập nội tuyến.
  • Nó không phải là thành ngữ.
  • Khi bạn đã xuất bản lớp học của mình và những người khác bắt đầu sử dụng nó, bạn đang mắc kẹt với nó: đã quá muộn để thay đổi nó để sử dụng phương pháp thay thế.

Nếu ý định của bạn với thuộc tính là làm cho mã ngắn gọn hơn, bạn không phải sử dụng từ "get" và "set" trong tên hàm của bạn; đó là một thực hành lỗi thời. Bạn có thể sử dụng tên thực tế của "tài sản" là tên hàm, và bạn có thể quá tải getter và setter:

class Cheque { 
public: 
    int x() const { 
     return x_; 
    } 
    Cheque & x(int newX) { 
     x_ = newX; 
     return *this; 
    } 
private: 
    int x_; 
} 

// Usage: 
// int amt = myCheque.x(1234); 
// Cheque c = Cheque().x(123); 

Trở *this như trong đoạn code trên cho phép bạn sử dụng method chaining; cách triển khai thành ngữ Fluent interface.

1

Khi C# biên dịch thích hợp, nó sẽ được biên dịch thành một hàm getter và hàm setter.

Dưới đây là một số mã C# để chứng minh thực tế này:

using System; 

namespace Reflect 
{ 
    class Program 
    { 
     class X 
     { 
      public int Prop { get; set; } 
     } 

     static void Main(string[] args) 
     { 
      var type = typeof(X); 
      foreach (var method in type.GetMethods()) 
      { 
       Console.WriteLine(method.Name); 
      } 
      Console.ReadKey(); 
     } 
    } 
} 

đầu ra của bạn nên là:

get_Prop 
set_Prop 
ToString 
Equals 
GetHashCode 
GetType 

get_Prop là chức năng mà thực hiện các getter. set_Prop là chức năng triển khai setter.

Vì vậy, ngay cả khi những gì bạn đang làm có vẻ tương tự, nó không giống nhau chút nào.

Thẳng thắn gần như mọi thứ bạn có thể làm để cố gắng mô phỏng cú pháp thuộc tính 'trong C++ sẽ rơi xuống theo cách này hay cách khác. Hầu hết các giải pháp sẽ chi phí cho bạn bộ nhớ hoặc nó sẽ có một số hạn chế mà làm cho nó cồng kềnh hơn hữu ích.

Chỉ cần học cách sống với getters và setters. Getters và setters là thực hành tốt. Chúng ngắn gọn, chúng đơn giản, chúng linh hoạt, chúng thường là những ứng cử viên tốt cho nội tuyến, mọi người đều hiểu những gì họ làm và cetera.

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