C ++ 'da “super” kullanımı


203

Kodlama tarzım aşağıdaki deyimi içerir:

class Derived : public Base
{
   public :
      typedef Base super; // note that it could be hidden in
                          // protected/private section, instead

      // Etc.
} ;

Bu, "süper" yi Base için bir takma ad olarak kullanmamı sağlıyor, örneğin yapıcılarda:

Derived(int i, int j)
   : super(i), J(j)
{
}

Ya da yöntemi, geçersiz kılınan sürümünün içindeki temel sınıftan çağırırken:

void Derived::foo()
{
   super::foo() ;

   // ... And then, do something else
}

Zincirleme bile olabilir (yine de bunun için kullanımı bulmak zorundayım):

class DerivedDerived : public Derived
{
   public :
      typedef Derived super; // note that it could be hidden in
                             // protected/private section, instead

      // Etc.
} ;

void DerivedDerived::bar()
{
   super::bar() ; // will call Derived::bar
   super::super::bar ; // will call Base::bar

   // ... And then, do something else
}

Her neyse, "Baseedef super" kullanımını çok yararlı buluyorum, örneğin Base ya ayrıntılı ve / veya şablonlu olduğunda.

Gerçek şu ki, süper Java'da ve C # 'da (yanlış olmadığım sürece "temel" olarak adlandırılır) uygulanır. Ancak C ++ bu anahtar kelimeden yoksundur.

Sorularım:

  • typedef super common / rare / bu kodun hiç görülmediği bir kullanımı var mı?
  • typedef super Ok'un bu kullanımı (yani kullanmamanız için güçlü veya çok güçlü olmayan nedenler görüyor musunuz?)
  • "süper" iyi bir şey olmalı, C ++ ile biraz standartlaştırılmalı mı, yoksa bu kullanım zaten bir typedef ile zaten yeterli mi?

Düzenleme: Roddy, typedef'in özel olması gerektiğinden bahsetti. Bu, türetilmiş herhangi bir sınıfın onu yeniden açıklamadan kullanamayacağı anlamına gelir. Ama sanırım süper :: süper zincirlemeyi de önleyecekti (ama bunun için kim ağlayacak?).

Edit 2: Şimdi, birkaç ay kitlesel olarak "süper" kullandıktan sonra, yürekten Roddy'nin bakış açısına katılıyorum: "süper" özel olmalı. Cevabını iki kez iptal ederdim, ama sanırım yapamam.


Müthiş! Tam aradığım şey. Şimdiye kadar bu tekniği kullanmam gerektiğini düşünmeyin. Platformlar arası kodum için mükemmel çözüm.
AlanKley

6
Benim için superbenziyor Javave kötü bir şey değil, ama ... Ama C++çoklu mirası destekliyor.
ST3

2
@ user2623967: Doğru. Basit miras durumunda, bir "süper" yeterlidir. Şimdi, birden fazla mirasınız varsa, "superA", "superB" vb.'ye sahip olmak iyi bir çözümdür: Yöntemi bir uygulamadan veya başka bir uygulamadan çağırmak istersiniz, bu yüzden istediğiniz uygulamayı söylemelisiniz. "Süper" benzeri typedef kullanmak, kolay erişilebilir / yazılabilir bir ad vermenizi sağlar ( MyFirstBase<MyString, MyStruct<MyData, MyValue>>her yere yazmak yerine )
paercebal

Bir şablondan devralırken, ona referans verirken şablon argümanlarını eklemeniz gerekmediğini unutmayın. Örneğin: template <class baz> struct Foo {...void bar() {...} ...}; struct Foo2: Foo<AnnoyinglyLongListOfArguments> { void bar2() { ... Foo::bar(); ...} };Bu bana gcc 9.1 --std = c ++ 1y (c ++ 14) ile çalıştı.
Thanasis Papoutsidakis

1
... ee, düzeltme. Sadece 14 değil, herhangi bir c ++ standardında çalışıyor gibi görünüyor
Thanasis Papoutsidakis

Yanıtlar:


152

Bjarne Stroustrup bahsedildi Tasarım ve C Evrim ++ o superbir anahtar kelime ISO C ++ Standartları Komitesi tarafından C ++ standardize edilmiş ilk kez kabul edildi olarak.

Dag Bruck bu uzantıyı önerdi ve temel sınıfı "kalıtsal" olarak adlandırdı. Teklif, çoklu miras sorunundan bahsetti ve belirsiz kullanımları işaretledi. Stroustrup bile ikna olmuştu.

Tartışmadan sonra Dag Bruck (evet, teklifi yapan aynı kişi) teklifin uygulanabilir, teknik olarak sağlam ve büyük kusurlardan arındırılmış olduğunu yazdı ve birden fazla miras ele aldı. Öte yandan, para için yeterli patlama olmadı ve komite daha zorlu bir sorunu ele almalı.

Michael Tiemann geç geldi ve daha sonra bu yazıda sorulan aynı tekniği kullanarak typedef'ed süper süper işe yarayacağını gösterdi.

Yani, hayır, bu muhtemelen asla standartlaşmayacaktır.

Bir kopyanız yoksa, Tasarım ve Evrim , kapak fiyatına değer. Kullanılmış kopyalar yaklaşık 10 $ karşılığında alınabilir.


5
D & E gerçekten iyi bir kitap. Ama tekrar okumam gerekecek gibi görünüyor - her iki hikayeyi de hatırlamıyorum.
Michael Burr

2
D&E'de tartışılan kabul edilmeyen üç özelliği hatırlıyorum. Bu ilk (hikayeyi bulmak için dizindeki "Michael Tiemann" a bakın), iki haftalık kural ikincisidir (dizindeki "iki hafta kuralı" konusuna bakın) ve üçüncüsü parametrelere (yukarı bak " adlı bağımsız değişkenler ".
Max Lybbert

12
typedefTeknikte büyük bir kusur var : DRY'ye uymuyor. Tek yol, sınıfları bildirmek için çirkin makrolar kullanmak olacaktır. Devralındığında, temel uzun bir çok parametreli şablon sınıfı veya daha kötü olabilir. (örneğin çoklu sınıflar) tüm bunları ikinci kez yeniden yazmanız gerekir. Son olarak, şablon sınıfı argümanları olan şablon tabanlarında büyük bir sorun görüyorum. Bu durumda, süper bir şablondur (ve şablonun somutlaştırılması değil). Hangi tip tanımlanamaz. C ++ 11'de bile usingbu durum için ihtiyacınız var .
v.oddou

105

Her zaman süper değil miras kaldım. (Muhtemelen bir Delphi arka plan nedeniyle) ve ben 'miras' yanlışlıkla bir sınıftan atlandı ama bir alt sınıf kullanmaya çalıştığında sorunu önlemek için, her zaman özel yapmak .

class MyClass : public MyBase
{
private:  // Prevents erroneous use by other classes.
  typedef MyBase inherited;
...

Yeni sınıflar oluşturmak için benim standart 'kod şablonu' typedef içerir, bu yüzden yanlışlıkla onu atlamak için çok az fırsatım var.

Zincirleme "süper :: süper" önerinin iyi bir fikir olduğunu sanmıyorum- Eğer bunu yapıyorsanız, muhtemelen belirli bir hiyerarşiye çok sıkı bağlısınız ve bunu değiştirmek muhtemelen kötü bir şekilde bozulacaktır.


2
Super :: super zincirlemesine gelince, soruda bahsettiğim gibi, hala ilginç bir kullanım alanı bulmam gerekiyor. Şimdilik, sadece bir kesmek olarak görüyorum, ancak sadece Java ile olan farklar için ("süper" zincirleyemediğinizde) bahsetmeye değerdi.
paercebal

4
Birkaç ay sonra, bakış açınıza dönüştürüldüm (ve bahsettiğiniz gibi unutulmuş bir "süper" yüzünden bir hata yaşadım ...). Zincirleme dahil cevabınızda oldukça haklısınız sanırım. ^ _ ^ ...
paercebal

bunu ana sınıf yöntemlerini çağırmak için nasıl kullanabilirim?
mLstudent33

tüm Base sınıfı yöntemlerini virtualburada gösterildiği gibi beyan etmem gerektiği anlamına gelir : martinbroadhurst.com/typedef-super.html
mLstudent33

36

Bununla ilgili bir sorun, türetilmiş sınıflar için super'i (yeniden-) tanımlamayı unutursanız, o zaman super :: bir şey çağrısı iyi derlenecek, ancak muhtemelen istenen işlevi çağırmayacaktır.

Örneğin:

class Base
{
public:  virtual void foo() { ... }
};

class Derived: public Base
{
public:
    typedef Base super;
    virtual void foo()
    {
        super::foo();   // call superclass implementation

        // do other stuff
        ...
    }
};

class DerivedAgain: public Derived
{
public:
    virtual void foo()
    {
        // Call superclass function
        super::foo();    // oops, calls Base::foo() rather than Derived::foo()

        ...
    }
};

(Bu cevabın yorumlarında Martin York'un işaret ettiği gibi, bu problem typedef'i herkese açık veya korunaklı hale getirerek ortadan kaldırılabilir.)


Yorum için teşekkürler. Bu yan etki benim dikkatimden kaçmıştı. Muhtemelen yapıcı kullanımı için derlenmeyecek olsa da, her yerde, sanırım, hata orada olurdu.
paercebal

5
Ancak, özel typedef, orijinal gönderide bahsedilen zincirleme kullanımı önleyecektir.
AnT

1
Bu soruna neden olan şey beni bu soruya yönlendiren şey :(
Steve Vermeulen

bu yüzden super1Base ve super2Derived için kullanın ? DerivedAgain her ikisini de kullanabilir mi?
mLstudent33

20

FWIW Microsoft, derleyicilerine __super için bir uzantı ekledi .


Buradaki birkaç geliştirici __super kullanmaya zorladı. İlk başta ben "yanlış" ve "standart dışı" olduğunu hissettim çünkü geri itti. ANCAK, onu sevmek için büyüdüm.
Aardvark

8
Bir windows uygulaması üzerinde çalışıyorum ve __super uzantısını seviyorum. Standartlar komitesinin burada belirtilen typedef hilesi lehine reddetmesi beni üzüyor, çünkü bu typedef hile iyi olsa da, miras hiyerarşisini değiştirdiğinizde bir derleyici anahtar kelimesinden daha fazla bakım gerektiriyor ve (iki gerek kalmadan) super1 ve super2 gibi typedefs). Kısacası, diğer yorumcuyla MS uzantısının ÇOK yararlı olduğunu kabul ediyorum ve Visual Studio'yu kullanan herkes onu kullanmayı kesinlikle düşünmelidir.
Brian

15

Süper (veya miras alınan) Çok İyi Bir Şeydir çünkü Base ile Derived arasında başka bir miras katmanı yapıştırmanız gerekiyorsa, yalnızca iki şeyi değiştirmeniz gerekir: 1. "sınıf Base: foo" ve 2. typedef

Doğru hatırlıyorsam, C ++ Standartları komitesi, Michael Tiemann bu typedef hilesinin işe yaradığına dikkat çekene kadar bunun için bir anahtar kelime eklemeyi düşünüyordu.

Çoklu mirasa gelince, programcı kontrolü altında olduğundan, istediğinizi yapabilirsiniz: belki super1 ve super2, ya da her neyse.


13

Alternatif bir çözüm buldum. Bugün beni bitiren typedef yaklaşımında büyük bir sorunum var:

  • Typedef, sınıf adının tam bir kopyasını gerektirir. Birisi sınıf adını değiştirir ancak typedef'i değiştirmezse sorun yaşarsınız.

Bu yüzden çok basit bir şablon kullanarak daha iyi bir çözüm buldum.

template <class C>
struct MakeAlias : C
{ 
    typedef C BaseAlias;
};

Şimdi, yerine

class Derived : public Base
{
private:
    typedef Base Super;
};

var

class Derived : public MakeAlias<Base>
{
    // Can refer to Base as BaseAlias here
};

Bu durumda, BaseAliasözel değildir ve diğer geliştiricileri uyarması gereken bir tür adı seçerek dikkatsiz kullanıma karşı korumaya çalıştım.


4
publicEğer bahsedilen hata açığız olarak takma, bir zararı olmaz Roddy en ve Kristopher en (örn Eğer (yanlışlıkla) elde edilebilir cevaplar Derivedyerine MakeAlias<Derived>)
Alexander Malakhov

3
Başlatıcı listelerinizdeki temel sınıf yapıcılarına da erişiminiz yok. (Bu, C ++ 11'de yapıcıları MakeAliasveya mükemmel yönlendirme miraslarını kullanarak telafi edilebilir , ancak MakeAlias<BaseAlias>sadece Cdoğrudan inşaatçılara atıfta bulunmak yerine inşaatçılara başvurmanızı gerektirir .)
Adam H. Peterson

12

Bunu daha önce gördüğümü hatırlamıyorum, ama ilk bakışta hoşuma gidiyor. As Ferruccio notları, bu MI karşısında iyi çalışmıyor, ancak MI kural daha istisna ve bir şey ihtiyaçları yararlı olduğu her yerde kullanılabilir olması için diyor bir şey yok.


6
Sadece "bir şeyin yararlı olması için her yerde kullanılabilir olması gerektiğini söyleyen hiçbir şey yok" ifadesini kullanın.
Tanktalus

1
Kabul. Bu kullanışlı. Ben sadece bir şablon aracılığıyla typedef oluşturmak için bir yol olup olmadığını görmek için boost türü özellikleri kitaplığı bakıyordu. Ne yazık ki, yapabileceğiniz gibi görünmüyor.
Ferruccio

9

Bu deyimin birçok kodda çalıştığını gördüm ve Boost'un kütüphanelerinde bir yerde bile gördüğümden eminim. Ancak, hatırladığım kadarıyla en yaygın isim base(veya Base) yerine super.

Bu deyim özellikle şablon sınıflarıyla çalışırken kullanışlıdır. Örnek olarak, aşağıdaki sınıfı düşünün ( gerçek bir projeden ):

template <typename TText, typename TSpec>
class Finder<Index<TText, PizzaChili<TSpec> >, PizzaChiliFinder>
    : public Finder<Index<TText, PizzaChili<TSpec> >, Default>
{
    typedef Finder<Index<TText, PizzaChili<TSpec> >, Default> TBase;
    // …
}

Komik isimleri aldırma. Burada önemli olan, kalıtım zincirinin derleme zamanı polimorfizmine ulaşmak için tip argümanları kullanmasıdır. Ne yazık ki, bu şablonların iç içe geçme seviyesi oldukça yükseliyor. Bu nedenle, kısaltmalar okunabilirlik ve sürdürülebilirlik için çok önemlidir.


"Süper" son zamanlarda aynı nedenle kullanmıştı. Kamu kalıtımı başka türlü ele almak için çok acı vericiydi ... :-) ...
paercebal


4

typedef super common / rare / bu kodun hiç görülmediği bir kullanımı var mı?

Çalıştığım C ++ kodunda bu özel deseni hiç görmedim, ama bu orada olmadığı anlamına gelmiyor.

typedef super Ok'un bu kullanımı (yani kullanmamanız için güçlü veya çok güçlü olmayan nedenler görüyor musunuz?)

Birden fazla mirasa izin vermez (temiz, her neyse).

"süper" iyi bir şey olmalı, C ++ ile biraz standartlaştırılmalı mı, yoksa bu kullanım zaten bir typedef ile zaten yeterli mi?

Yukarıda belirtilen nedenden ötürü (çoklu miras), no. Listelediğiniz diğer dillerde "süper" ifadesini görmenizin nedeni, yalnızca tek mirası destekledikleri için "süper" nin ne anlama geldiğiyle ilgili bir karışıklık yoktur. Bu dillerde faydalıdır, ancak C ++ veri modelinde gerçekten bir yeri yoktur.

Oh, ve FYI: C ++ / CLI bu kavramı "__super" anahtar kelimesi biçiminde destekler. Bununla birlikte, C ++ / CLI'nın birden fazla kalıtım özelliğini de desteklemediğini lütfen unutmayın.


4
Karşı-nokta olarak, Perl birden çok devralma hem de sahiptir ve SUPER. Biraz karışıklık var, ancak VM'nin bir şey bulmak için geçtiği algoritma açıkça belgeleniyor. Bununla birlikte, nadiren çoklu baz sınıflarının karışıklığın yine de ortaya çıkabileceği aynı yöntemleri sunduğu yerlerde MI kullanıldığını görüyorum.
Tanktalus

1
Microsoft Visual Studio, CLI için olsun veya olmasın, C ++ için __super anahtar sözcüğünü uygular. Miras alınan sınıflardan sadece biri doğru imza yöntemi (Tanktalus tarafından belirtildiği gibi en yaygın durum) sunuyorsa, sadece geçerli seçimi seçer. İki veya daha fazla devralınan sınıf bir işlev eşleşmesi sağlarsa, çalışmaz ve açık olmanızı gerektirir.
Brian

3

Üst sınıf için typedef kullanmanın başka bir nedeni, nesnenin mirasında karmaşık şablonlar kullanmaktır.

Örneğin:

template <typename T, size_t C, typename U>
class A
{ ... };

template <typename T>
class B : public A<T,99,T>
{ ... };

B sınıfında A için bir typedef olması idealdir, aksi takdirde A'nın üyelerine atıf yapmak istediğiniz her yerde tekrar edersiniz.

Bu durumlarda da çoklu kalıtımla çalışabilir, ancak 'super' adında bir typedefiniz olmaz, buna 'base_A_t' veya bunun gibi bir şey denir.

--jeffk ++


2

Gün içinde Turbo Pascal'dan C ++ 'a geçtikten sonra, aynı şekilde çalışan Turbo Pascal "devralınan" anahtar kelimesine eşdeğer olmak için bunu yapardım. Ancak, birkaç yıl boyunca C ++ 'da programlama yaptıktan sonra yapmayı bıraktım. Çok fazla ihtiyacım olmadığını gördüm.


1

Nadir olup olmadığını bilmiyorum, ama kesinlikle aynı şeyi yaptım.

Belirtildiği gibi, dilin bu parçasını kendisinin yapmanın zorluğu, bir sınıfın birden fazla kalıtımdan faydalanmasıdır.


1

Bunu zaman zaman kullanıyorum. Kendimi temel sınıf türünü birkaç kez yazarken bulduğumda, sizinkine benzer bir typedef ile değiştireceğim.

Bence iyi bir kullanım olabilir. Dediğiniz gibi, temel sınıfınız bir şablonsa yazmayı kaydedebilir. Ayrıca şablon sınıfları, şablonun nasıl çalışması gerektiğine ilişkin politikalar olarak işlev gören bağımsız değişkenler alabilir. Tabanın arayüzü uyumlu olduğu sürece, tüm referanslarınızı düzeltmek zorunda kalmadan taban türünü değiştirmekte özgürsünüz.

Bence typedef'in kullanımı zaten yeterli. Zaten dilin nasıl oluşturulacağını göremiyorum çünkü çoklu kalıtım birçok temel sınıf olabileceği anlamına gelir, bu yüzden mantıksal olarak en önemli temel sınıf olduğunu düşündüğünüz sınıf için uygun gördüğünüz gibi bunu tanımlayabilirsiniz.


1

Ben de aynı sorunu çözmeye çalışıyordum; Rastgele sayıda ebeveyne izin vermek için varyasyonlu şablonlar ve paket genişletme gibi birkaç fikir attım, ancak bunun 'super0' ve 'super1' gibi bir uygulama ile sonuçlanacağını fark ettim. Onu çöpe attım, çünkü bu başlamak için olmamaktan çok daha yararlı olurdu.

Çözümüm bir yardımcı sınıf içerir PrimaryParentve şu şekilde uygulanır:

template<typename BaseClass>
class PrimaryParent : virtual public BaseClass
{
protected:
    using super = BaseClass;
public:
    template<typename ...ArgTypes>
    PrimaryParent<BaseClass>(ArgTypes... args) : BaseClass(args...){}
}

O zaman hangi sınıfı kullanmak istediğiniz belirtilir:

class MyObject : public PrimaryParent<SomeBaseClass>
{
public:
    MyObject() : PrimaryParent<SomeBaseClass>(SomeParams) {}
}

PrimaryParentTarihinde sanal kalıtım kullanma ihtiyacından kaçınmak için BaseClass, değişken sayıda argüman alan bir kurucu, yapımına izin vermek için kullanılır BaseClass.

Sebebi publicmirası BaseClassINTO PrimaryParentizin vermektir MyObjectmirası üzerinde üzerinde tam kontrole sahip BaseClassaralarında bir yardımcı sınıf olmasına rağmen.

Bu, sahip olmak istediğiniz her sınıfın yardımcı sınıfı superkullanması gerektiği anlamına gelir PrimaryParentve her çocuk PrimaryParent(dolayısıyla adı) kullanarak yalnızca bir sınıftan miras alabilir .

Bu yöntem için bir başka kısıtlama MyObject, miras alan sadece bir sınıfı miras alabilir PrimaryParentve bu sınıfın miras alınması gerekir PrimaryParent. Demek istediğim şu:

class SomeOtherBase : public PrimaryParent<Ancestor>{}

class MixinClass {}

//Good
class BaseClass : public PrimaryParent<SomeOtherBase>, public MixinClass
{}


//Not Good (now 'super' is ambiguous)
class MyObject : public PrimaryParent<BaseClass>, public SomeOtherBase{}

//Also Not Good ('super' is again ambiguous)
class MyObject : public PrimaryParent<BaseClass>, public PrimaryParent<SomeOtherBase>{}

Görünen kısıtlamalar ve her miras arasında bir orta sınıf olduğu için bunu bir seçenek olarak atmadan önce, bunlar kötü değildir.

Çoklu kalıtım güçlü bir araçtır, ancak çoğu durumda, sadece bir birincil ebeveyn olacaktır ve başka ebeveynler varsa, muhtemelen Mixin sınıfları veya yine de kalıtımsal olmayan sınıflar olacaktır PrimaryParent. Birden fazla miras hala gerekliyse (birçok durum, miras yerine bir nesneyi tanımlamak için kompozisyonu kullanmanın yararına olsa da), sadece supero sınıfta açıkça tanımlamak ve miras almamaktır PrimaryParent.

superHer sınıfta tanımlamak zorunda kalmak benim için çok cazip değil , mirasa dayalı bir takma ad kullanmak, verilerin gitmesi gereken sınıf gövdesi yerine sınıf tanımlama satırında kalmasına PrimaryParentizin veriyor super.

Yine de bu ben olabilirim.

Elbette her durum farklıdır, ancak hangi seçeneği kullanacağınıza karar verirken söylediğim şeyleri göz önünde bulundurun.


1

Süper arama tabanı anlamına gelmediğini gösteren yorumları ile mevcut kod dışında çok demeyeceğim!

super != base.

Kısacası, "süper" ne anlama geliyor? ve sonra "temel" ne anlama geliyor?

  1. süper, bir yöntemin son uygulayıcısını çağırmak anlamına gelir (taban yöntemi değil)
  2. base, hangi sınıfın çoklu mirasta varsayılan temel olacağını seçmek anlamına gelir.

Bu 2 kural sınıf tip tanımlamaları için geçerlidir.

Kütüphane uygulayıcısı ve kütüphane kullanıcısını düşünün, kim süper ve kim tabanlıdır?

daha fazla bilgi için IDE'nize kopyala yapıştır için çalışma kodu:

#include <iostream>

// Library defiens 4 classes in typical library class hierarchy
class Abstract
{
public:
    virtual void f() = 0;
};

class LibraryBase1 :
    virtual public Abstract
{
public:
    void f() override
    {
        std::cout << "Base1" << std::endl;
    }
};

class LibraryBase2 :
    virtual public Abstract
{
public:
    void f() override
    {
        std::cout << "Base2" << std::endl;
    }
};

class LibraryDerivate :
    public LibraryBase1,
    public LibraryBase2
{
    // base is meaningfull only for this class,
    // this class decides who is my base in multiple inheritance
private:
    using base = LibraryBase1;

protected:
    // this is super! base is not super but base!
    using super = LibraryDerivate;

public:
    void f() override
    {
        std::cout << "I'm super not my Base" << std::endl;
        std::cout << "Calling my *default* base: " << std::endl;
        base::f();
    }
};

// Library user
struct UserBase :
    public LibraryDerivate
{
protected:
    // NOTE: If user overrides f() he must update who is super, in one class before base!
    using super = UserBase; // this typedef is needed only so that most derived version
    // is called, which calls next super in hierarchy.
    // it's not needed here, just saying how to chain "super" calls if needed

    // NOTE: User can't call base, base is a concept private to each class, super is not.
private:
    using base = LibraryDerivate; // example of typedefing base.

};

struct UserDerived :
    public UserBase
{
    // NOTE: to typedef who is super here we would need to specify full name
    // when calling super method, but in this sample is it's not needed.

    // Good super is called, example of good super is last implementor of f()
    // example of bad super is calling base (but which base??)
    void f() override
    {
        super::f();
    }
};

int main()
{
    UserDerived derived;
    // derived calls super implementation because that's what
    // "super" is supposed to mean! super != base
    derived.f();

    // Yes it work with polymorphism!
    Abstract* pUser = new LibraryDerivate;
    pUser->f();

    Abstract* pUserBase = new UserBase;
    pUserBase->f();
}

Burada bir diğer önemli nokta şudur:

  1. polimorfik çağrı: aşağıya doğru çağırır
  2. süper çağrı: yukarı doğru aramalar

içinde main(), süper hayatta yukarı doğru çağıran, gerçek hayatta gerçekten yararlı olmayan polimorfik çağrı aşağıları kullanıyoruz, ancak farkı gösteriyor.



0

Bu bir typedef yerine makro kullanan bir yöntemdir. Bunun bir şeyleri yapmanın C ++ yolu olmadığını biliyorum, ancak sadece hiyerarşinin en aşağısında temel sınıf kalıtımsal bir ofset üzerinde hareket ettiğinde yineleyicileri miras yoluyla zincirlerken uygun olabilir.

Örneğin:

// some header.h

#define CLASS some_iterator
#define SUPER_CLASS some_const_iterator
#define SUPER static_cast<SUPER_CLASS&>(*this)

template<typename T>
class CLASS : SUPER_CLASS {
   typedef CLASS<T> class_type;

   class_type& operator++();
};

template<typename T>
typename CLASS<T>::class_type CLASS<T>::operator++(
   int)
{
   class_type copy = *this;

   // Macro
   ++SUPER;

   // vs

   // Typedef
   // super::operator++();

   return copy;
}

#undef CLASS
#undef SUPER_CLASS
#undef SUPER

Kullandığım genel kurulum, yinelenen kod içeren ancak geçersiz kılınması gereken devralma ağacı arasında okumayı ve kopyala / yapıştırmayı çok kolaylaştırır, çünkü dönüş türü geçerli sınıfla eşleşmelidir.

Bir daha düşük durumda kullanabilirsiniz superJava görülen davranış çoğaltmak için ama benim kodlama tarzı makrolar için tüm büyük harfler kullanmaktır.

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.