C ++ sendikalarını oldukça havalı buluyorum. Görünüşe göre, insanlar sadece bir kişinin "yerinde" bir sendika örneğinin değerini değiştirmek istediği kullanım örneğini düşünüyor gibi görünüyor (ki bu sadece hafızadan tasarruf etmeye veya şüpheli dönüşümler gerçekleştirmeye hizmet ediyor).
Aslında sendikalar , hiçbir sendika örneğinin değerini asla değiştirmediğinizde bile , bir yazılım mühendisliği aracı olarak büyük bir güce sahip olabilirler .
Kullanım örneği 1: bukalemun
Sendikalarla, bir temel sınıf ve onun türetilmiş sınıfları ile benzerlik göstermeyen bir mezhep altında bir dizi rasgele sınıfı yeniden gruplandırabilirsiniz. Bununla birlikte, değişen birlik, belirli bir sendika örneğiyle yapabileceğiniz ve yapamayacağınız şeydir:
struct Batman;
struct BaseballBat;
union Bat
{
Batman brucewayne;
BaseballBat club;
};
ReturnType1 f(void)
{
BaseballBat bb = {/* */};
Bat b;
b.club = bb;
// do something with b.club
}
ReturnType2 g(Bat& b)
{
// do something with b, but how do we know what's inside?
}
Bat returnsBat(void);
ReturnType3 h(void)
{
Bat b = returnsBat();
// do something with b, but how do we know what's inside?
}
Programcının kullanmak istediği belirli bir sendika örneğinin içeriğinden emin olması gerektiği anlaşılıyor. f
Yukarıdaki işlevde durum böyledir . Bununla birlikte, bir işlev g
yukarıdaki gibi olduğu gibi geçirilmiş bir argüman olarak bir birleşim örneği alacak olsaydı, bununla ne yapacağını bilemezdi. Aynısı sendika örneğini döndüren işlevler için de geçerlidir, bkz h
: arayan kişi içeride ne olduğunu nasıl bilebilir?
Bir sendika örneği asla bir argüman veya dönüş değeri olarak geçilmezse, programcı içeriğini değiştirmeyi seçtiğinde çok monoton bir hayata sahip olmak heyecanlıdır:
Batman bm = {/* */};
Baseball bb = {/* */};
Bat b;
b.brucewayne = bm;
// stuff
b.club = bb;
Ve bu, sendikaların en yaygın kullanım örneğidir. Bir başka kullanım örneği, sendika örneğinin size türünü söyleyen bir şeyle birlikte gelmesidir.
Kullanım örneği 2: "Güzel Ben, tanıştığımıza object
gelen, Class
"
Bir sendika örneğini her zaman tür tanımlayıcıyla eşleştirmek için seçilmiş bir programcı olduğunu varsayalım (bu tür bir nesne için bir uygulama hayal etmek için onu okuyucunun takdirine bırakacağım). Programlayıcının istediği şey hafızayı korumaksa ve tür tanımlayıcısının büyüklüğünün sendikaya göre ihmal edilemez olması durumunda, bu sendikanın amacını yener. Ancak diyelim ki sendika örneğinin, içeride ne olduğunu bilmeyen callee veya arayan ile bir argüman olarak veya bir dönüş değeri olarak geçirilebilmesi çok önemlidir.
Sonra programcı switch
Bruce Wayne'e tahta bir çubuktan ya da eşdeğeri bir şeyden bahsetmek için bir kontrol akışı bildirimi yazmalıdır. Birlikte yalnızca iki tür içerik olduğunda çok kötü değil, ama açıkça, birlik artık ölçeklenmiyor.
Kullanım örneği 3:
ISO C ++ Standardı için bir tavsiyenin yazarlarının 2008'de tekrar belirttiği gibi,
Birçok önemli sorun alanı, çok sayıda nesne veya sınırlı bellek kaynağı gerektirir. Bu durumlarda alandan tasarruf etmek çok önemlidir ve bir birlik genellikle bunu yapmak için mükemmel bir yoldur. Aslında, yaygın bir kullanım örneği, bir birliğin yaşamı boyunca hiçbir zaman aktif üyesini değiştirmediği durumdur. Sadece bir üye içeren bir yapı gibi inşa edilebilir, kopyalanabilir ve imha edilebilir. Bunun tipik bir uygulaması, dinamik olarak tahsis edilmemiş (belki de bir haritada veya bir dizinin üyelerinde yerinde oluşturulmuş) ilişkisiz türlerin heterojen bir koleksiyonunu oluşturmak olacaktır.
Ve şimdi, bir örnek, UML sınıf diyagramı ile:
Düz İngilizce durum: A sınıfı bir nesne olabilir B1 arasında herhangi sınıfın nesneleri, ..., Bn ve her tür çoğu biri de n oldukça büyük bir sayı olmak en az 10 söylerler.
A'ya aşağıdaki gibi alanlar (veri üyeleri) eklemek istemiyoruz:
private:
B1 b1;
.
.
.
Bn bn;
çünkü n değişebilir (karışıma Bx sınıfları eklemek isteyebiliriz), çünkü bu yapıcılar için karışıklığa neden olacağından ve A nesneleri çok fazla yer kaplayacağından.
Onları almak için dökümleri void*
olan Bx
nesnelere tuhaf bir işaretçi konteyneri kullanabiliriz , ancak bu çirkin ve çok C tarzı ... ama daha da önemlisi, bizi yönetmek için dinamik olarak tahsis edilen birçok nesnenin ömrünü bırakacaktı.
Bunun yerine ne yapılabilir:
union Bee
{
B1 b1;
.
.
.
Bn bn;
};
enum BeesTypes { TYPE_B1, ..., TYPE_BN };
class A
{
private:
std::unordered_map<int, Bee> data; // C++11, otherwise use std::map
public:
Bee get(int); // the implementation is obvious: get from the unordered map
};
Daha sonra, bir birleşim örneğinin içeriğini almak için şunu data
kullanın a.get(TYPE_B2).b2
ve benzerleri, burada a
sınıf A
örneği.
C ++ 11'de sendikalar sınırsız olduğu için bu daha da güçlü. Ayrıntılar için yukarıdaki belgeye veya bu makaleye bakın.