Üye işlevleri ve matematik işleçleri için üye olmayan işlevler


12

Matrisler, vektörler, vb. İçeren doğrusal bir cebir kütüphanesi (uzun öykü kısa, bir okul ödevi) yazıyorum. Bu kütüphaneyi oluşturma sürecinde, nesneler üzerinde matematiksel işlemler yapan işlevler yaratacağım. Örneğin, devrik matris, ters matris, vektörü normalleştir vb.

Bu tür bir işlev için "en iyi uygulama" nın ne olduğunu merak ettim ... Yani, bu işlevi bir üye işlevi olarak mı yoksa üye olmayan olarak mı yapmalıyım? (Açıklık / kütüphane için aşkına)

Misal:

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

Bu tür operasyonlarla ilgili bir standart var mı? Ya da en azından insanların bunu yapmasının ortak bir yolu var mı? İlk seçeneğe yöneliyorum, ancak bunun tavsiye edilip edilmediğini bilmek istiyorum.

Yanıtlar:


7

Bu sadece bir stil ve tat meselesi. Farklı lineer cebir kütüphaneleri de gördüm

  • üye işlevlerini kullanarak OOP stilinde yazılmış

  • OOP olmayan bir tarzda, sadece serbest fonksiyonlar kullanılarak yazılmıştır

  • her ikisiyle birlikte bir API sağlama

ve hepsi çalışıyordu. En azından API'nız tutarlı olmalıdır, bu nedenle seçiminizi yapın ve bu stilleri rastgele karıştırmamaya dikkat edin.


8

Üyelik ücretlerinden kaçının: Mümkünse, üyesi olmayanları işlevsiz hale getirmeyi tercih edin.

Üye olmayan arkadaş olmayan işlevler bağımlılıkları en aza indirerek kapsüllemeyi geliştirir: İşlevin gövdesi sınıfın halka açık olmayan üyelerine bağlı olamaz (bkz. Madde 11). Ayrıca, ayrılabilir işlevselliği serbest bırakmak ve birleşmeyi daha da azaltmak için monolitik sınıfları ayırırlar (bkz. Madde 33). Jenerikliği geliştirirler, çünkü bir işlemin belirli bir türe üye olup olmadığını bilmeyen şablonlar yazmak zordur [...]

Herb Sutter


1
Sonunda iyi bir cevap: Geç, ama çok geç değil. ;-) Başka bir referans: GotW # 84: Monoliths "Unstrung"
Deduplicator

1

Hem üye hem de üye olmayan işlevlerin sadece tadının yanı sıra gerçek avantajları vardır. Örneğin, bir matrixsınıfı uygulamak için kullanılan temel dizi (ler) muhtemelen üye işlevlerini privatekullanmadığınız friendsürece kullanmanız gerekecektir . Bu bakımdan, bir OO tasarımı daha iyi olabilir.

Ancak, bilgisayar bilimcilerinin zaman zaman gerçekten ne yaptığını bilmeden karmaşık matematik formülü uygulamak zorunda olduklarını unutmayın. Bunu yapmak zorunda olduğumda, "görsel" sonuç orijinal matematik formülüne daha yakın olacağı için üye olmayan işlevleri tercih ederim (çünkü matematik formülü genellikle işlevsel bir stil kullanır).

Sonunda cevap Doc Brown'ın cevabı ile aynıdır: bu bir zevk meselesi. Kısacası, üye işlevleriyle (yazması daha kolay, hayır friend) OO tarzı bir kitaplık yazmayı, daha sonra argümanlarını üye olanlara iletecek aynı görevleri yapmak için üye olmayan işlevleri yazmayı düşünebilirsiniz . Tutarlı olmanıza ve kullanıcının en iyi olduğunu düşündüğü şeyi seçmesine izin vermenizi sağlar.


0

Sorun bildiriminizde daha ayrıntılı bilgi verirseniz, bir noktada belirli matematiksel varlıkları temsil eden özel veri yapılarını kullanacağınız açıktır. Örneğin, n boyutlu bir dizi için bir matrisi temsil edebilirsin. Örneğiniz hakkında ayrıntı vermek için,

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

(C ++ örneği basitleştirilmiştir, şablonları vb. Kullanabilirsiniz.)

Dikkate alınması gereken nokta, her iki durumda da özel veri yapılarının kullanım kolaylığıdır. C ++ (veya herhangi bir nesne yönelimli) bir dil olarak kendi içinde daha güçlüdür ve bu, uygulayıcının yararına olduğu kadar kütüphanenin tüketicisine de uzanır. Geçmişte sadece C kütüphanelerini kullandım ve bu özel veri yapıları çok kısa sürede her yere ulaşıyor gibi görünüyor! İkincisi ile birlikte çalışabilirlik elde etmek daha kolayken (özel kurucular kullanarak, belki?)

Onu sarmak için, C ++ kullanıyorsanız, nesne odaklı bir yaklaşım kesinlikle önerilir.


5
Maalesef, akıl yürütmenizde çok az sağlam gerçek var. İki transposeörneğiniz arasında kullanım kolaylığı açısından fark yoktur . C ++ yani daha kolay olmasının temel nedeni, kopyalama ve atama anlambiliminin gerçekten çalışmasıdır. A = BC derleme olabilir ama muhtemelen yanlış bir şey yapar.
MSalters

Kopya semantiği için +1 Karşılaşmaya çalıştığım nokta, gevşek bağlı yapılar kümesi ve ilgili işlevler kullanarak nesneleri ("gösterimler" üzerinde kapsülleme) v / s kullanmaktır.
dotbugfix
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.