2010-12-31 20 views
9

Tek bir ortak arabirim sağlamak için genel bir kapsayıcı türü oluşturmaya ve değiştirmeye tabi oldukları için kullandığım iç kapsayıcıları gizlemeye çalışıyorum.C++ 'da Genel Kapsayıcı

Temel olarak, öğe koleksiyonlarını döndüren eklentilerim var ve eklentilerin kodun kullandığı kapsayıcı türünün farkında olmasını istemiyorum.

kimse daha sonra daha iyi bir yönde aşağıdaki örnek kodda işaret edebilir?

template<class C, typename I> 
class Container 
{ 
public: 
//... 

    void push(const I& item) 
    { 
     if(typeid(C) == typeid(std::priority_queue<I>)) 
     { 
      std::priority_queue<I>* container = (std::priority_queue<I>*)&_container; 
      container->push(item); 
     } 
     if(typeid(C) == typeid(std::list<I>)) 
     { 
      std::list<I>* container = (std::list<I>*)&_container; 
      container->push_back(item); 
     } 
     else 
     { 
      //error! 
     } 
    }; 

    private: 
    C _container; 
//... 
} 

teşekkürler "ortak bir arayüz" yazdı

+4

. Bunu yapma. Uygulamanızı tasarlarken zamanınızı harcayın, böylece statik olarak yazılan kapsayıcılar kullanır. – ybungalobill

+1

Daha iyi yönde işaret edebilir, emin: ** ** bunu yapmak çalışmayın. Ciddi anlamda. Sana hiçbir şey kazandırmayacak. Burada konuşan deneyimin sesi. –

+6

Neden burada düşüş var? Bu gayet meşru bir soru. Cevap “bu şekilde yapma” olsa bile, hala geçerli bir soruydu. – Tim

cevap

6

Öğelerin koleksiyonlarını döndüren eklentilerim var ve eklentilerimin kodun kullandığı kapsayıcı türünün farkında olmasını istemiyorum.

eklentilerinizde uygun gördüğünüz gibi aralığını tüketmek ardından öğelerin koleksiyonlarına içine begin ve end yineleyicinızı sağlamak ve var.

Yineleyicilerin en büyük avantajı, verilerin nasıl kullanıldığına (kapsayıcı), verilerin nasıl kullanıldığına (kapsayıcı), (sizin durumunuzda, eklenti verilerini tüketen uygulama kodunuza) tam olarak ayrılmasına izin vermeleridir.

Bu şekilde, eklentilerin verilerini nasıl sakladıklarına ve eklentilerin size verdiklerinde verdikleri bilgilerle ilgilendikleri şeylere sahip olmadıklarına bakmak zorunda kalmazsınız. Yukarıdaki gibi bir sınıfla

+0

Yanıtlarınız için teşekkürler James. Ancak bu yaklaşım gözüktü ancak sahnede dişler ortaya çıktığında kıllı hale geldi. Örneğin, bir DataStore eklentisi, değişken validator ids ile çoklu threadlar tarafından çağrılabilen get_events (int validator_id) yöntemine sahip olabilir. – Corvusoft

+2

@ user: Anlamıyorum; Bir yineleyici arabiriminin konteynır arabiriminden daha fazla eşzamanlılık sorunu yoktur: kapsayıcıyı üzerinde yineleme yaparken kapsayıcıyı kilitleyin veya kapsayıcının yinelemesi için bir kopyasını yapın. –

+0

+1. Ancak, dahili olarak farklı bir kap tipi kullanan yolda yeni bir eklenti oluşturulduğunda eklentinin dönüş değerlerini tüketen kodun yeniden derlenmesinin gerekmediğini düşünmekteyim - bu durumda, nasıl? Görünüşe göre yineleyicileri 'begin()' ve 'end()' temel sınıflar (arayüzler) tarafından kendi başlarına döndürmeleri ve onlara saf sanal işlevsellik ++() 've' operatör *() ' vb yöntemler; Daha sonra, kullanılan her bir kap tipi için, doğru tipte yineleyici için uygun yönteme yönlendiren somut bir alt sınıf oluşturun, doğru mu? Tricky görünüyor ... –

0

Biliyorsun, ben standart konteyner sarın soyut bir sınıf ve alt sınıf ile bir şey Java tarzını göstermek için gittiğini emindim. Bir grup tipli çağrı görmek için şaşırdım ...

Ama sonra, neden bunu yapmak istiyorsunuz? Çoğu konteyner ortak bir arayüzü paylaşır ve SFINAE'nin gücü ile özel kod yazmanız bile gerekmez! Sadece şablonları kullanın ve doğrudan yöntemi arayın.

DÜZENLEME: Standart kapsayıcıların sanal yöntemleri olmadığını ve bu nedenle, dynamic_cast ed olamaz.

0

Başlat, senin eklentileri ihtiyaç duyduğu minimum arayüzü maruz. Sonra kullanacağınız konteynır açısından uygulayın. Buna kapsayıcı bağdaştırıcısı denir ve std :: yığınının nasıl uygulandığıdır.

Daha fazla bir STL kabı için şablona gerçekten ihtiyacınız varsa, şablonla devam edin, std :: stack bölümüne bakın, bunu nasıl yapacağınızı gösterecektir. Bunu neden isteyeyim

, TypeId açmayın?

BTW, konteynerin kendisini ortaya çıkarmak için bir ihtiyaç olmadığı sürece James anlaşılacağı ile gitmek.

elimden