Fungsi anggota vs. Fungsi bukan anggota untuk operator matematika

12

Saya sedang menulis perpustakaan aljabar linier (cerita panjang, ini adalah tugas sekolah) yang melibatkan matriks, vektor, dll. Dalam proses membuat perpustakaan ini, saya akan membuat fungsi yang melakukan operasi matematika pada objek. Misalnya, transpos matriks, invert matrix, normalisasi vektor, dll.

Saya ingin tahu apa "praktik terbaik" untuk fungsi semacam ini ... Artinya, apakah saya harus menjadikan fungsi tersebut sebagai fungsi anggota, atau bukan anggota? (Demi kejelasan / penggunaan perpustakaan)

Contoh:

//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);

Apakah ada standar untuk operasi semacam ini? Atau, setidaknya, adakah cara yang umum dilakukan orang-orang ini? Saya condong ke opsi pertama, tetapi saya ingin tahu apakah ini direkomendasikan.

apnorton
sumber

Jawaban:

7

Ini hanya masalah gaya dan selera. Saya telah melihat perpustakaan aljabar linier yang berbeda, baik

  • ditulis dalam gaya OOP menggunakan fungsi anggota

  • ditulis dalam gaya non-OOP hanya menggunakan fungsi gratis

  • menyediakan API dengan keduanya

dan mereka semua bekerja. Paling tidak, API Anda harus konsisten, jadi pilihlah pilihan Anda dan pastikan Anda tidak mencampur gaya-gaya itu secara sewenang-wenang.

Doc Brown
sumber
8

Hindari biaya keanggotaan: Jika memungkinkan, lebih suka membuat fungsi yang bukan anggota bukan teman.

Fungsi non-anggota yang bukan anggota meningkatkan enkapsulasi dengan meminimalkan ketergantungan: Badan fungsi tidak dapat bergantung pada anggota kelas yang bukan publik dari kelas (lihat Butir 11). Mereka juga memecah kelas monolitik untuk membebaskan fungsi yang dapat dipisahkan, lebih lanjut mengurangi kopling (lihat Item 33). Mereka meningkatkan kedermawanan, karena sulit untuk menulis templat yang tidak tahu apakah operasi adalah anggota untuk jenis tertentu [...]

Sutera Ramuan


sumber
1
Akhirnya jawaban yang bagus: Terlambat, tetapi tidak terlambat. ;-) Referensi lain: GotW # 84: Monoliths "Unstrung"
Deduplicator
1

Baik fungsi anggota dan non-anggota memiliki keunggulan nyata selain rasa. Sebagai contoh, array yang mendasari yang digunakan untuk mengimplementasikan matrixkelas mungkin akan private, oleh karena itu, Anda harus menggunakan friendkecuali jika Anda menggunakan fungsi anggota. Dalam hal ini, desain OO mungkin lebih baik.

Namun, perlu diingat bahwa, dari waktu ke waktu, ilmuwan komputer harus menerapkan rumus matematika yang rumit tanpa selalu tahu apa yang sebenarnya Anda lakukan. Ketika saya harus melakukannya, saya lebih suka fungsi non-anggota karena hasil "visual" akan lebih dekat dengan rumus matematika asli (karena rumus matematika umumnya menggunakan gaya fungsional).

Pada akhirnya, jawabannya sama dengan jawaban Doc Brown: ini masalah selera. Singkatnya, Anda dapat mempertimbangkan untuk menulis pustaka gaya OO dengan fungsi anggota (lebih mudah untuk menulis, tidak friend), kemudian menulis fungsi non-anggota untuk melakukan tugas yang sama yang hanya akan meneruskan argumen mereka ke pustaka anggota. Ini memungkinkan Anda untuk konsisten dan membiarkan pengguna memilih apa yang menurutnya terbaik.

Morwenn
sumber
0

Jika Anda menyelam lebih dalam pada pernyataan masalah Anda, jelas bahwa pada titik tertentu Anda akan menggunakan struktur data kustom yang mewakili entitas matematika tertentu. Sebagai contoh, Anda mungkin mewakili matriks cara saya dari array n-dimensi. Untuk menguraikan contoh Anda,

// 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();

(Contoh C ++ disederhanakan, Anda dapat menggunakan templat dan semacamnya.)

Poin yang perlu dipertimbangkan adalah kemudahan menggunakan struktur data khusus dalam kedua kasus. C ++ (atau objek yang berorientasi) sebagai bahasa lebih kuat dalam dirinya sendiri, dan itu meluas ke konsumen perpustakaan sebanyak itu bermanfaat bagi pelaksana. Saya telah menggunakan pustaka C saja di masa lalu dan struktur data tersuai itu tampaknya dapat menyebar ke semua tempat dalam waktu singkat! Sedangkan interoperabilitas lebih mudah dicapai dengan yang terakhir (menggunakan konstruktor khusus, mungkin?)

Untuk menyelesaikannya, jika Anda menggunakan C ++ maka pendekatan berorientasi objek pasti direkomendasikan.

perbaikan dotbug
sumber
5
Maaf, ada sedikit fakta kuat dalam alasan Anda. Tidak ada perbedaan dalam kemudahan penggunaan antara dua transposecontoh Anda. Alasan utama C ++ yaitu lebih mudah adalah karena copy dan semantik tugas benar-benar berfungsi. A = Bdapat dikompilasi dalam C tetapi mungkin melakukan hal yang salah.
MSalters
+1 untuk menyalin semantik Titik yang saya coba sampaikan adalah menggunakan objek (enkapsulasi lebih dari "representasi") v / s menggunakan set struktur dan fungsi terkait yang digabungkan secara longgar.
dotbugfix