在c++中继承模板类

时间:2022-09-07 07:53:56

Let's say we have a template class Area, which has a member variable T area, a T getArea() and a void setArea(T) member functions.

假设我们有一个模板类Area,它有一个成员变量T area,一个T getArea()和一个void setArea(T)成员函数。

I can create an Area object of a specific type by typing Area<int>.

我可以通过键入Area 来创建特定类型的Area对象。

Now I have a class Rectangle that inherits the Area class. Since Rectangle itself is not a template, I cannot type Rectangle<int>.

现在我有一个继承Area类的Rectangle类。由于Rectangle本身不是模板,因此我无法输入Rectangle

How do I specialize the inherited Area type for Rectangle objects?

如何为Rectangle对象专门化继承的Area类型?

EDIT: Sorry, I forgot to clarify - my questions is whether it is possible to inherit Area without specializing it, so it is not inherited as Area of ints but as Area Rectangle can specialize the types for.

编辑:对不起,我忘了澄清 - 我的问题是是否可以继承区域而不专门化它,因此它不会作为整数区域继承,但区域矩形可以专门化类型。

6 个解决方案

#1


156  

For understanding templates, it's of huge advantage to get the terminology straight because the way you speak about them determines the way to think about them.

为了理解模板,将术语直截了当是非常有利的,因为你谈论它们的方式决定了思考它们的方式。

Specifically, Area is not a template class, but a class template. That is, it is a template from which classes can be generated. Area<int> is such a class (it's not an object, but of course you can create an object from that class in the same ways you can create objects from any other class). Another such class would be Area<char>. Note that those are completely different classes, which have nothing in common except for the fact that they were generated from the same class template.

具体来说,Area不是模板类,而是类模板。也就是说,它是一个可以从中生成类的模板。 Area 就是这样一个类(它不是一个对象,但当然你可以用与从任何其他类创建对象相同的方式从该类创建一个对象)。另一个这样的类是Area 。请注意,这些是完全不同的类,除了它们是从同一个类模板生成的事实之外没有任何共同之处。

Since Area is not a class, you cannot derive the class Rectangle from it. You only can derive a class from another class (or several of them). Since Area<int> is a class, you could, for example, derive Rectangle from it:

由于Area不是类,因此无法从中派生类Rectangle。您只能从另一个类(或其中几个)派生一个类。由于Area 是一个类,因此您可以从中派生Rectangle:

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

Since Area<int> and Area<char> are different classes, you can even derive from both at the same time (however when accessing members of them, you'll have to deal with ambiguities):

由于Area 和Area 是不同的类,您甚至可以同时从这两个类派生(但是当访问它们的成员时,您将不得不处理歧义):

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

However you have to specify which classed to derive from when you define Rectangle. This is true no matter whether those classes are generated from a template or not. Two objects of the same class simply cannot have different inheritance hierarchies.

但是,您必须指定在定义Rectangle时从哪个类派生。无论这些类是否是从模板生成,都是如此。同一类的两个对象根本不能具有不同的继承层次结构。

What you can do is to make Rectangle a template as well. If you write

你可以做的是使Rectangle成为一个模板。如果你写

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

You have a template Rectangle from which you can get a class Rectangle<int> which derives from Area<int>, and a different class Rectangle<char> which derives from Area<char>.

你有一个模板Rectangle,你可以从中获得一个派生自Area 的Rectangle 类,以及一个派生自Area 的不同类Rectangle

It may be that you want to have a single type Rectangle so that you can pass all sorts of Rectangle to the same function (which itself doesn't need to know the Area type). Since the Rectangle<T> classes generated by instantiating the template Rectangle are formally independent of each other, it doesn't work that way. However you can make use of multiple inheritance here:

可能您希望拥有单个类型的Rectangle,以便可以将各种Rectangle传递给同一个函数(它本身不需要知道Area类型)。由于通过实例化模板Rectangle生成的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);
}

If it is important that your generic Rectangle is derived from a generic Area you can do the same trick with Area too:

如果通用Rectangle派生自通用区域非常重要,那么您也可以使用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
};

#2


11  

Are you just trying to derive from Area<int>? In which case you do this:

你只是想从Area 派生出来吗?在这种情况下,你这样做:

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

EDIT: Following the clarification, it seems you're actually trying to make Rectangle a template as well, in which case the following should work:

编辑:在澄清之后,似乎你实际上也试图使Rectangle成为一个模板,在这种情况下,以下应该有效:

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

#3


7  

class Rectangle : public Area<int> {
};

#4


5  

Make Rectangle a template and pass the typename on to Area:

使Rectangle成为模板并将typename传递给Area:

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

};

#5


4  

Rectangle will have to be a template, otherwise it is just one type. It cannot be a non-template whilst its base magically is. (Its base may be a template instantiation, though you seem to want to maintain the base's functionality as a template.)

Rectangle必须是一个模板,否则它只是一种类型。它不可能是非模板,而它的基础是神奇的。 (它的基础可能是模板实例化,但您似乎希望将基础功能保留为模板。)

#6


0  

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

#1


156  

For understanding templates, it's of huge advantage to get the terminology straight because the way you speak about them determines the way to think about them.

为了理解模板,将术语直截了当是非常有利的,因为你谈论它们的方式决定了思考它们的方式。

Specifically, Area is not a template class, but a class template. That is, it is a template from which classes can be generated. Area<int> is such a class (it's not an object, but of course you can create an object from that class in the same ways you can create objects from any other class). Another such class would be Area<char>. Note that those are completely different classes, which have nothing in common except for the fact that they were generated from the same class template.

具体来说,Area不是模板类,而是类模板。也就是说,它是一个可以从中生成类的模板。 Area 就是这样一个类(它不是一个对象,但当然你可以用与从任何其他类创建对象相同的方式从该类创建一个对象)。另一个这样的类是Area 。请注意,这些是完全不同的类,除了它们是从同一个类模板生成的事实之外没有任何共同之处。

Since Area is not a class, you cannot derive the class Rectangle from it. You only can derive a class from another class (or several of them). Since Area<int> is a class, you could, for example, derive Rectangle from it:

由于Area不是类,因此无法从中派生类Rectangle。您只能从另一个类(或其中几个)派生一个类。由于Area 是一个类,因此您可以从中派生Rectangle:

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

Since Area<int> and Area<char> are different classes, you can even derive from both at the same time (however when accessing members of them, you'll have to deal with ambiguities):

由于Area 和Area 是不同的类,您甚至可以同时从这两个类派生(但是当访问它们的成员时,您将不得不处理歧义):

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

However you have to specify which classed to derive from when you define Rectangle. This is true no matter whether those classes are generated from a template or not. Two objects of the same class simply cannot have different inheritance hierarchies.

但是,您必须指定在定义Rectangle时从哪个类派生。无论这些类是否是从模板生成,都是如此。同一类的两个对象根本不能具有不同的继承层次结构。

What you can do is to make Rectangle a template as well. If you write

你可以做的是使Rectangle成为一个模板。如果你写

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

You have a template Rectangle from which you can get a class Rectangle<int> which derives from Area<int>, and a different class Rectangle<char> which derives from Area<char>.

你有一个模板Rectangle,你可以从中获得一个派生自Area 的Rectangle 类,以及一个派生自Area 的不同类Rectangle

It may be that you want to have a single type Rectangle so that you can pass all sorts of Rectangle to the same function (which itself doesn't need to know the Area type). Since the Rectangle<T> classes generated by instantiating the template Rectangle are formally independent of each other, it doesn't work that way. However you can make use of multiple inheritance here:

可能您希望拥有单个类型的Rectangle,以便可以将各种Rectangle传递给同一个函数(它本身不需要知道Area类型)。由于通过实例化模板Rectangle生成的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);
}

If it is important that your generic Rectangle is derived from a generic Area you can do the same trick with Area too:

如果通用Rectangle派生自通用区域非常重要,那么您也可以使用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
};

#2


11  

Are you just trying to derive from Area<int>? In which case you do this:

你只是想从Area 派生出来吗?在这种情况下,你这样做:

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

EDIT: Following the clarification, it seems you're actually trying to make Rectangle a template as well, in which case the following should work:

编辑:在澄清之后,似乎你实际上也试图使Rectangle成为一个模板,在这种情况下,以下应该有效:

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

#3


7  

class Rectangle : public Area<int> {
};

#4


5  

Make Rectangle a template and pass the typename on to Area:

使Rectangle成为模板并将typename传递给Area:

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

};

#5


4  

Rectangle will have to be a template, otherwise it is just one type. It cannot be a non-template whilst its base magically is. (Its base may be a template instantiation, though you seem to want to maintain the base's functionality as a template.)

Rectangle必须是一个模板,否则它只是一种类型。它不可能是非模板,而它的基础是神奇的。 (它的基础可能是模板实例化,但您似乎希望将基础功能保留为模板。)

#6


0  

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