C ++의 템플릿 클래스에서 상속


106

Area멤버 변수 T area, a T getArea()void setArea(T)멤버 함수 가있는 템플릿 클래스가 있다고 가정 해 보겠습니다 .

Area을 입력하여 특정 유형 의 개체를 만들 수 있습니다 Area<int>.

이제 클래스 Rectangle를 상속하는 Area클래스가 있습니다. 이후 Rectangle자체가 서식하지, 내가 입력 할 수 없습니다 Rectangle<int>.

상속 된 객체 Area유형을 어떻게 전문화 Rectangle합니까?

편집 : 죄송합니다, 명확하게하는 것을 잊었습니다-내 질문은 Area를 전문화하지 않고 상속 할 수 있는지 여부입니다. 따라서 Area Rectangle이 유형을 전문화 할 수 있기 때문에 Int 영역으로 상속되지 않습니다.


3
그것은의 클래스 템플릿 은 클래스가 생성되는 템플릿이기 때문에.
sbi

1
@sbi 여기서 불꽃 전쟁을 시작할 생각은 없지만 Bjarne Stroustrup이 클래스 템플릿템플릿 클래스를 구분하지 않는다면 ( The C ++ Programming Language , 4th ed., section 23.2.1 참조) 둘 다.
Michael Warner

@MichaelWarner 나는 그가 구별을 만드는 것을 기억하는 것 같습니다. 그러나 그것은 Usenet에서 90 년대였습니다. 그 이후로 포기했을 수도 있습니다. (아니면 인스턴스화 된 클래스 템플릿을 템플릿 클래스로 참조 할 수 있습니까?)
sbi

답변:


244

템플릿을 이해하는 데있어 용어에 대해 말하는 방식에 따라 생각하는 방식이 결정되기 때문에 용어를 바로 잡는 것이 큰 이점입니다.

구체적으로 특별히, Area 템플릿 클래스가 아니라 클래스 템플릿입니다. 즉, 클래스를 생성 할 수있는 템플릿입니다. Area<int>이러한 클래스는 (그것의입니다 하지 객체,하지만 물론 당신이 다른 클래스에서 개체를 만들 수 있습니다 같은 방법으로 그 클래스에서 개체를 만들 수 있습니다). 또 다른 클래스는 Area<char>. 이들은 완전히 다른 클래스이며 동일한 클래스 템플릿에서 생성되었다는 사실을 제외하고는 공통점이 없습니다.

Area클래스가 아니기 때문에 클래스를 파생시킬 수 없습니다.Rectangle 를 . 다른 클래스 (또는 여러 클래스)에서만 클래스를 파생 할 수 있습니다. Area<int>클래스 이므로 예를 들어 다음과 같이 파생 할 수 Rectangle있습니다.

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

Area<int>Area<char>클래스가 다르기 때문에 동시에 둘 다에서 파생시킬 수도 있습니다 (하지만 멤버에 액세스 할 때 모호성을 처리해야합니다).

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

그러나 정의 할 때 파생 할 클래스를 지정해야합니다 Rectangle. 이는 해당 클래스가 템플릿에서 생성되었는지 여부에 관계없이 적용됩니다. 동일한 클래스의 두 개체는 다른 상속 계층을 가질 수 없습니다.

당신이 할 수있는 일은 Rectangle템플릿도 만드는 것입니다. 쓰면

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

에서 파생되는 Rectangle클래스 Rectangle<int>와에서 파생되는 Area<int>다른 클래스 Rectangle<char>를 가져올 수 있는 템플릿 이 있습니다 Area<char>.

동일한 함수에 Rectangle모든 종류를 전달할 수 있도록 단일 유형을 원할 수 있습니다 Rectangle(자체가 Area 유형을 알 필요가 없음). 이후Rectangle<T> 템플릿을 인스턴스화하여 생성 된 클래스가 Rectangle서로 공식적으로 독립, 그것은 그런 식으로 작동하지 않습니다. 그러나 여기에서 다중 상속을 사용할 수 있습니다.

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);
}

제네릭 Rectangle이 제네릭 에서 파생되는 것이 중요한 경우 Area동일한 트릭을 사용할 수도 Area있습니다.

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
};

참고 : 템플릿 유형 매개 변수는 해당 클래스 템플릿을 인스턴스화하는 객체 클래스의 일부입니다. 즉, 클래스의 구성 요소가 아니라 유형의 일부입니다.
Nikos

21

당신은 단지에서 파생하려고 Area<int>합니까? 이 경우 다음을 수행합니다.

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

편집 : 설명에 따라 실제로 Rectangle템플릿도 만들려고하는 것 같습니다 .이 경우 다음이 작동합니다.

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


8

Rectangle을 템플릿으로 만들고 Typename을 Area에 전달합니다.

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

};

6

Rectangle템플릿이어야합니다. 그렇지 않으면 하나의 유형일뿐 입니다. 마술처럼 기본이되는 동안 템플릿이 될 수 없습니다. (기본 기능 을 템플릿으로 유지하려는 것처럼 보이지만 기본은 템플릿 인스턴스화 일 수 있습니다 .)


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();
}

파생 클래스에 메서드가 있다면 어떨까요? 그것들을 어떻게 정의 하시겠습니까? 그리고 대부분의 가져 오기는 적어도 나에게 main () 함수에서 이러한 메서드를 어떻게 호출 / 사용합니까?
Pototo 2017-06-02

6
첫째, 이것은 이미 훌륭한 답변을 가지고있는 정말 오래된 질문입니다. 둘째, 코드 일 뿐인 답변 (및 질문)은 피하십시오. 자세한 설명도 포함하는 것이 유용합니다.
marcman
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.