2010-09-01 15 views
12

Sanal temel sınıfın bir nesnesini geri getirebilmeyi diliyorum, böylece bellek yönetimi ile uğraşmaya gerek kalmayacak (fonksiyon programlaması fikri de bu arayışı tetikler). Ancak, arayüz tasarımında her zaman bir işaretçi sınıfına geri dönmelidir?

class Car 
{ 
    public: 
    virtual int price() = 0 ; 
    virtual string brand() = 0 ; 
} 

class Interface 
{ 
    public: 
    virtual Car giveMeACar() = 0 ; 
    virtual vector<Car> listMeAllTheCars() = 0 ; 
} 

, bu bile Araba soyut arayüz nedeniyle derlemek olmaz, bir hata mesajı ile:

geçersiz soyut dönüş tipi Ben aşağıda gibi bazı şeyler arıyorum anlamına gelir üye fonksiyon 'virtual Car giveMeACar() = 0; Aşağıdaki sanal işlevler , 'Car' içinde '
string brand(); Akıllı işaretçi kullanma seçeneği dışarı iktidar -

Yani, (kullandıktan sonra örneğini silme) Kendim altında ve yöneticisi hafıza gibi revize etmek şeye arayüze sahip demektir yapar.

class Interface 
{ 
    public: 
    virtual Car* giveMeACar() = 0 ; 
    virtual vector<Car*> listMeAllTheCars() = 0 ; 
} 

Sorum şu: Bu elimdeki tek seçenek olduğunda tasarım her şey (sınıfı) soyut bir arayüz?

Arabirim sınıfının bir nesnesinin döndürülmesi, Java'da mükemmel geçerlidir. C++, bu faset içinde çöp bitleri ve sayaçları sezgisel gibi görünüyor. Çoğu zaman, C++ 'nun bir "nesne programlama dili" yerine "programlama dilini nesneye yönlendirmesi" olduğunu hissediyorum; çünkü bir işaretçi olmadan, nesne programlamasının çok fazla faydası olmaz.

+0

Sanal işlevler yapmak için +1 özel: – Chubsdad

+1

@chubsdad : Neden? Bu benim niyetim değil ... Ben kamu – pierrotlefou

+1

-1 kullanmış olmalı, sonra Sanal Sanal Arayüz deyimine bakın. Örneğin, ortak yöntemler sanalysa, arabirimlerinizin sınırlarında değişmezleri uygulayamazsınız. –

cevap

7

Stick aslında C++ nesneye bir işaretçi dönen anlam eşdeğer olduğunu, bunun bir kopyasını oluşturur değeri, bir nesneyi döndürmek için çalışıyoruz. Soyut bir nesnenin bir kopyasını yapamazsın. C++ daha ayrıntılı olabilirken

yani, Java (değeriyle dönüş referans ile bu geçiş) desteklemez, hangi değerleri parametreleri geçen ve döndürme için farklı semantik destekler. Bunun üzerine

sizin için bellek yönetimini yapar akıllı pointer ile dönmek gerektiğini söyledi. Eğer (örneğin bir havuz) dahili olarak özel bellek ayırmayı kullanmak durumunda, Diğerleri sahipliği aktarım semantik ile auto_ptr işaret, ama aynı zamanda boost::shared_ptr kullanabilirsiniz shared_ptr 'ın özel deleter özelliği arayüzünün kullanıcıdan deallocation ayrıntılarını gizlemek yardımcı olacaktır. STL konteynerlerinde de kullanılabilir (auto_ptr'den farklı olarak).

class Car 
{ 
public: 
    typedef boost::shared_ptr<Car> Ptr; 
    virtual int price() = 0 ; 
    virtual string brand() = 0 ; 
}; 

class Interface 
{ 
public: 
    virtual Car::Ptr giveMeACar() = 0 ; 
    virtual vector<Car::Ptr> listMeAllTheCars() = 0 ; 
} 
+0

Takviye ettikten sonra sözdizimini seviyorum. Ancak, gömülü bir proje için, çaprazlama ve beklenmedik bir sorun derleme görevi her zaman beni kullanarak onu uzak tutar ... – pierrotlefou

+0

@pierr, evet boost bir domuz biraz, ama 'shared_ptr' sadece başlık uygulaması vardır herhangi bir destek kütüphanesine bağlamanız gerekmez. Derleyicinizin 'std :: tr1 :: shared_ptr' (GCC 4+, özellik paketi ile MSVC 2008) destekleyip desteklemediğini de kontrol edebilirsiniz. –

+0

Neyse ki, çapraz derleyicim desteği std :: tr1 :: shared_ptr – pierrotlefou

1

Sanırım this kullanımdan olabilir.

+2

, bağlantı ... –

4

Gözlemleriniz doğru, yapmak istediğiniz şeyi yapmak için kolay bir yolu yoktur. C++'da, bir araca değer veremezsiniz, çünkü (diğer şeylerin yanında) arayanın bunun için alan ayırması gerekir.

Java temelde farklı değil, yalnızca sözdizimini ifade etmek istediğiniz şeyleri ifade edemez, her tür (ilkel türler hariç) bunlara eklenmiş bir '*' içerir. Ve çöp koleksiyonuna sahip, bu yüzden bellek yönetimi konusunda endişelenmenize gerek yok.

template<class CarClass> 
class Interface { 
    virtual CarClass giveMeACar() = 0; 
    virtual vector<CarClass> listMeAllTheCars() = 0; 
} 
+0

siz "kendi sözdizimi ifade etmek istediğini ifade CAN" kastettiniz açar bazı ipucu varsa bu güzel? – pierrotlefou

+2

Hayır, "yapamaz" demek istedim. Java, bir sınıfa değer verme eylemini ifade edemez. Tüm sınıflar gizli olarak referans olarak geçmiştir. Muhtemelen en yakın Java "Car x = giveMeACar();" C++ 'da "Car x = (Car) giveMeACar(). clone();" (Araba klon yöntemini doğru uygularsa). –

+0

Kafam karıştı. Java daima değere geçmelidir. http://stackoverflow.com/questions/40480/is-java-pass-by-reference – pierrotlefou

2

Diğer seçenek bir şablon kullanmaktır. Nesneyi bir işaretçi gibi yığının üstüne koyar, ancak bir yığın değişkeni gibi kapsam dışına çıktığında onu siler.

Değişiklikler, auto_ptr numaralarını içeren boost::unique_ptr ve C++ 0x std::unique_ptr içerir.

, ile değiştirilemez, çünkü auto_ptr kapsayıcılarla uyumsuzdur. Bunun için unique_ptr kullanmanız gerekir.

3

Return bir std::auto_ptr<Car>:

+0

Ve bu işaretçi türleri arasında geçiş yapmak için doğaçlama, yazılabilirlik ve tek bakım noktası için (daha sonra performans için gerekli ise), bir yazım hatası oluşturmak isteyebilirsiniz. Bu oldukça yaygın bir yaklaşım. –

+1

[Tebrikler!] (Http://stackoverflow.com/badges/49/c?userid=153285) –

0

Sorunuza yanıt olarak diğer gönderiler, sorgunuzu mükemmel bir şekilde yanıtlar.

kaçının dış dünyaya uygulanması ile ilgili ayrıntıları açığa: Ancak, ben sadece

İlk gözlem düşünebiliriz birkaç gözlemler vardı.

Bu

virtual vector<Car> listMeAllTheCars() = 0 ; dönüş türü ile ilgili olup. Eğer vector veya list veya başka bir şey kullanıyorsanız

Neden sınıfın kullanıcılarının bilmeliyim? GOF'tan Iterator Design Pattern'e göz atın. C++ yineleyiciler için iyi bir desteğe sahiptir.

İkinci gözlem:

İhtiyaçlarınız ben

virtual Car giveMeACar() = 0 ;

bakmak özellikle sen Fabrika yöntemi Design Pattern bakmak isteyebilirsiniz Fabrika Yöntemi tasarım deseni ihtiyacını taklit görünüyor

Üçüncü gözlem:

Ancak bu eğlenceli hem varlığı Tek bir arayüzde kurgular, benim için az yer kaplıyor. Tasarımı tekrar düşünmek isteyebilirsiniz. "Dönen ve nesne", Java'da Single Responsibility Principle.

İlgili konular