C ++ 'da bir şablon sınıfından devralma


106

Diyelim ki Areaüye değişkeni T area, a T getArea()ve void setArea(T)üye fonksiyonları olan bir şablon sınıfımız var .

AreaYazarak belirli türde bir nesne oluşturabilirim Area<int>.

Şimdi sınıfı Rectanglemiras alan bir Areasınıfım var. Yana Rectanglekendisi şablonu değil, ben yazamaz Rectangle<int>.

Nesneler için devralınan Areatürü nasıl uzmanlaştırabilirim Rectangle?

DÜZENLEME: Üzgünüm, açıklığa kavuşturmayı unuttum - benim sorularım Alan'ı uzmanlaşmadan devralmanın mümkün olup olmadığıdır, bu yüzden Alan İntler Alanı olarak miras alınmaz, ancak Alan Dikdörtgeni için türleri özelleştirebilir.


4
Bu var sınıf şablonu o sınıfları üretildikleri bir şablon çünkü.
sbi

1
@sbi Burada bir alev savaşı başlatmak niyetinde değilim, ancak Bjarne Stroustrup sınıf şablonu ile şablon sınıfı arasında bir ayrım yapmazsa (bkz . C ++ Programlama Dili , 4. baskı, bölüm 23.2.1), o zaman yapmalısınız Ya da.
Michael Warner

@MichaelWarner Ayrımı yaptığını hatırlıyorum. Bu 90'lı yıllarda Usenet'teydi. Belki o zamandan beri vazgeçmiştir. (Ya da belki örneklenmiş bir sınıf şablonunu bir şablon sınıf olarak ifade eder?)
sbi

Yanıtlar:


245

Şablonları anlamak için, terminolojiyi doğru anlamak çok büyük bir avantajdır çünkü onlar hakkında konuşma şekliniz onlar hakkında düşünme şeklinizi belirler.

Özellikle, Areabir şablon sınıf değil, bir sınıf şablonudur. Yani, sınıfların üretilebileceği bir şablondur. Area<int>böyle bir sınıftır (bu bir nesne değildir , ancak elbette, başka herhangi bir sınıftan nesneler oluşturabildiğiniz yollarla o sınıftan bir nesne oluşturabilirsiniz). Böyle bir başka sınıf olacaktır Area<char>. Bunların tamamen farklı sınıflar olduğunu ve aynı sınıf şablonundan oluşturulmuş olmaları dışında hiçbir ortak yanları olmadığını unutmayın.

Yana Areabir sınıf değil, sınıfı elde edemez Rectangleondan. Yalnızca başka bir sınıftan (veya birkaçından) bir sınıf türetebilirsiniz. Yana Area<int>bir sınıftır, sen, örneğin, elde edebileceğini Rectangleondan:

class Rectangle:
  public Area<int>
{
  // ...
};

Yana Area<int>ve Area<char>farklı sınıflar vardır, aynı anda (bunların üyelerini erişirken ancak, belirsizlikleri ile uğraşmak gerekecek) her iki kaynaklanıyor bile yapabilirsiniz:

class Rectangle:
  public Area<int>,
  public Area<char>
{
  // ...
};

Bununla birlikte, tanımladığınızda hangi sınıflandırmanın türetileceğini belirtmeniz gerekir Rectangle. Bu, bu sınıfların bir şablondan oluşturulmuş olup olmadığına bakılmaksızın geçerlidir. Aynı sınıftaki iki nesnenin farklı miras hiyerarşileri olamaz.

Yapabileceğiniz şey Rectanglebir şablon yapmaktır . Eğer yazarsan

template<typename T> class Rectangle:
  public Area<T>
{
  // ...
};

Bir şablon var Rectanglebir sınıf alabilirsiniz hangi Rectangle<int>türetilmiştir Area<int>ve farklı bir sınıf Rectangle<char>türetilmiştir Area<char>.

Tek bir türe sahip olmak isteyebilirsiniz, Rectangleböylece her türden Rectangleaynı işleve geçebilirsiniz (Alan türünü bilmesine gerek yoktur). Yana Rectangle<T>örneklenimin tarafından oluşturulan sınıfları Rectanglebirbirinden resmen bağımsız, bu şekilde çalışmıyor. Bununla birlikte, burada çoklu kalıtımdan yararlanabilirsiniz:

class Rectangle // not inheriting from any Area type
{
  // Area independent interface
};

template<typename T> class SpecificRectangle:
  public Rectangle,
  public Area<T>
{
  // Area dependent stuff
};

void foo(Rectangle&); // A function which works with generic rectangles

int main()
{
  SpecificRectangle<int> intrect;
  foo(intrect);

  SpecificRectangle<char> charrect;
  foo(charrect);
}

Jenerik ürününüzün bir jenerikten Rectangletüretilmesi önemliyse Area, aynı numarayı Areada yapabilirsiniz:

class Area
{
  // generic Area interface
};

class Rectangle:
  public virtual Area // virtual because of "diamond inheritance"
{
  // generic rectangle interface
};

template<typename T> class SpecificArea:
  public virtual Area
{
  // specific implementation of Area for type T
};

template<typename T> class SpecificRectangle:
  public Rectangle, // maybe this should be virtual as well, in case the hierarchy is extended later
  public SpecificArea<T> // no virtual inheritance needed here
{
  // specific implementation of Rectangle for type T
};

Not: Bir şablon türü parametresi, o sınıf şablonunu başlatan bir nesne sınıfının parçasıdır. Başka bir deyişle, sınıfın bir bileşeni değil, türün bir parçası.
Nikos

21

Sadece türetmeye Area<int>mi çalışıyorsun ? Bu durumda şunu yaparsınız:

class Rectangle : public Area<int>
{
    // ...
};

DÜZENLEME: Açıklamayı takiben, aslında Rectanglebir şablon oluşturmaya çalıştığınız anlaşılıyor , bu durumda aşağıdakiler çalışmalıdır:

template <typename T>
class Rectangle : public Area<T>
{
    // ...
};


8

Dikdörtgen'i bir şablon yapın ve tip adını Alan'a iletin:

template <typename T>
class Rectangle : public Area<T>
{

};

6

Rectangleşablon olması gerekecek, aksi takdirde sadece bir türdür . Temeli sihirli bir şekilde olduğu halde şablon dışı olamaz. ( Temeli , bir şablon somutlaştırması olabilir , ancak temelin işlevselliğini bir şablon olarak korumak isteyebilirsiniz .)


3
#include<iostream>

using namespace std;

template<class t> 
class base {
protected:
    t a;
public:
    base(t aa){
        a = aa;
        cout<<"base "<<a<<endl;
    }
};

template <class t> 
class derived: public base<t>{
    public:
        derived(t a): base<t>(a) {
        }
        //Here is the method in derived class 
    void sampleMethod() {
        cout<<"In sample Method"<<endl;
    }
};

int main() {
    derived<int> q(1);
    // calling the methods
    q.sampleMethod();
}

türetilmiş sınıfta yöntemleriniz varsa ne olur? Onları nasıl tanımlarsın? Ve şimdiye kadarki çoğu içe aktarma, en azından benim için, bu yöntemleri main () işlevinizde nasıl çağırır / kullanırsınız?
Pototo

6
Birincisi, bu zaten harika bir cevabı olan gerçekten eski bir sorudur. İkinci olarak, lütfen yalnızca kod olan yanıtlardan (ve sorulardan) kaçının. Ayrıntılı açıklamaların eklenmesi de faydalıdır.
marcman
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.