Hàm thành viên so với hàm không phải thành viên cho toán tử toán học


12

Tôi đang viết thư viện đại số tuyến tính (truyện ngắn, đó là bài tập của trường) liên quan đến ma trận, vectơ, v.v. Trong quá trình tạo thư viện này, tôi sẽ tạo các hàm thực hiện các phép toán trên các đối tượng. Ví dụ, ma trận chuyển vị, ma trận đảo ngược, vectơ chuẩn hóa, v.v.

Tôi tò mò không biết "cách thực hành tốt nhất" cho loại chức năng này là gì ... Nghĩa là tôi nên biến chức năng này thành chức năng thành viên hay không phải là thành viên? (Để rõ ràng / sử dụng thư viện vì lợi ích)

Thí dụ:

//Member function way:
B = A.transpose();
C = A.inverse();

//Non-member function way:
B = linalg::transpose(A); //Non-member transpose function in linear algebra namespace
C = linalg::inverse(A);

Có một số tiêu chuẩn liên quan đến các loại hoạt động? Hoặc, ít nhất, có một cách phổ biến mọi người làm điều này? Tôi đang nghiêng về lựa chọn đầu tiên, nhưng tôi muốn biết liệu điều này có được khuyến nghị không.

Câu trả lời:


7

Đây chỉ là một vấn đề về phong cách và hương vị. Tôi đã thấy các thư viện đại số tuyến tính khác nhau, hoặc

  • được viết theo kiểu OOP bằng các hàm thành viên

  • được viết theo kiểu không OOP chỉ sử dụng các chức năng miễn phí

  • cung cấp API với cả hai

và tất cả bọn họ đang làm việc Ít nhất, API của bạn phải nhất quán, vì vậy hãy chọn lựa chọn của bạn và đảm bảo bạn không trộn lẫn các kiểu đó một cách tùy tiện.


8

Tránh phí thành viên: Nếu có thể, thích thực hiện các chức năng không phải là bạn bè.

Các hàm nonfriend tháng không cải thiện việc đóng gói bằng cách giảm thiểu các phụ thuộc: Phần thân của hàm không thể phụ thuộc vào các thành viên không công khai của lớp (xem Mục 11). Họ cũng phá vỡ các lớp nguyên khối để giải phóng chức năng có thể tách rời, tiếp tục giảm khớp nối (xem Mục 33). Chúng cải thiện tính tổng quát, bởi vì thật khó để viết các mẫu mà không biết liệu một hoạt động có phải là thành viên cho một loại nhất định hay không [...]

Thảo dược


1
Cuối cùng là một câu trả lời hay: Muộn, nhưng không quá muộn. ;-) Một tài liệu tham khảo: GotW # 84: Tảng đá nguyên khối "chùng"
Deduplicator

1

Cả hai chức năng thành viên và không thành viên đều có lợi thế thực sự bên cạnh hương vị đơn thuần. Ví dụ, (các) mảng cơ bản được sử dụng để triển khai một matrixlớp có thể sẽ là privatedo đó, bạn sẽ phải sử dụng friendtrừ khi bạn sử dụng các hàm thành viên. Về mặt này, một thiết kế OO có thể tốt hơn.

Tuy nhiên, hãy nhớ rằng, theo thời gian, các nhà khoa học máy tính phải thực hiện công thức toán học phức tạp mà không phải luôn biết những gì thy thực sự làm. Khi tôi phải làm như vậy, tôi đặt trước các hàm không phải là thành viên vì kết quả "trực quan" sẽ gần với công thức toán học ban đầu hơn (vì công thức toán học thường sử dụng một kiểu hàm).

Cuối cùng, câu trả lời cũng giống như câu hỏi của Doc Brown: đó là vấn đề về hương vị. Nói tóm lại, bạn có thể xem xét việc viết thư viện kiểu OO với các hàm thành viên (dễ viết hơn, không viết friend), sau đó viết các hàm không phải thành viên để thực hiện các tác vụ tương tự sẽ đơn giản chuyển tiếp các đối số của chúng cho các thành viên. Nó cho phép bạn nhất quán và để người dùng chọn những gì anh ta cho là tốt nhất.


0

Nếu bạn đi sâu hơn vào tuyên bố vấn đề của mình, rõ ràng đến một lúc nào đó bạn sẽ sử dụng các cấu trúc dữ liệu tùy chỉnh đại diện cho các thực thể toán học nhất định. Chẳng hạn, bạn có thể biểu diễn một ma trận phương tiện của tôi là mảng n chiều. Để giải thích về ví dụ của bạn,

// C way
typedef struct {
    int data[MAX_LEN][MAX_LEN];
} MATRIX;

MATRIX B = transpose(A);

// C++ way
class Matrix; // Forward Declaration
class Matrix {
    int data[MAX_LEN][MAX_LEN];
    public:
        Matrix transpose();
};

Matrix B = A.transpose();

(Ví dụ về C ++ được đơn giản hóa, bạn có thể sử dụng các mẫu và như vậy.)

Điểm cần xem xét là dễ sử dụng cấu trúc dữ liệu tùy chỉnh trong cả hai trường hợp. C ++ (hoặc bất kỳ đối tượng nào hướng đến) như một ngôn ngữ mạnh hơn, và điều đó mở rộng đến người tiêu dùng của thư viện nhiều như nó mang lại lợi ích cho người thực hiện. Trước đây tôi đã sử dụng các thư viện C và các cấu trúc dữ liệu tùy chỉnh đó dường như xuất hiện ở mọi nơi ngay lập tức! Trong khi đó khả năng tương tác dễ dàng đạt được hơn với cái sau (có thể sử dụng các hàm tạo đặc biệt?)

Để kết thúc, nếu bạn đang sử dụng C ++ thì nên sử dụng phương pháp hướng đối tượng.


5
Xin lỗi, có rất ít sự thật vững chắc trong lý luận của bạn. Không có sự khác biệt về tính dễ sử dụng giữa hai transposeví dụ của bạn . Lý do chính C ++ tức là dễ dàng hơn là vì ngữ nghĩa sao chép và gán thực sự hoạt động. A = Bcó thể biên dịch trong C nhưng có thể làm điều sai.
MSalters

+1 cho ngữ nghĩa sao chép Điểm tôi đã cố gắng vượt qua là sử dụng các đối tượng (đóng gói trên "biểu diễn") v / s bằng cách sử dụng tập hợp các cấu trúc và các chức năng liên quan.
dotormsfix
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.