如何创建Derived类并在创建派生类时实例化Base类。
喜欢这个
template<class T>
struct Base
{
typedef T type;
static const int n = 3;
virtual int f() = 0;
int f(int x) { return x * 2; }
};
// doesn't compile!
template<class T>
struct Derived : Base<T>
{
type field; // The compiler doesn't know Base<T>::type yet!
int f() { return n; } // the compiler doesn't know n yet, and f(int) is maksed!
};
答案 0 :(得分:3)
您可以使用using
声明引入相关名称:
template<class T>
struct Base
{
typedef T type;
static const int n = 3;
virtual int f() = 0;
int f(int x) { return x * 2; }
};
template<class T>
struct Derived : Base<T>
{
using typename Base<T>::type;
using Base<T>::n;
type field;
int f() { return n; }
};
对于以这种方式继承的类型,您还必须使用typename
关键字(如上所述),以便编译器知道名称是指类型。有一个question on SO,其中包含有关此要求的更多信息。
另一种方法是明确限定名称:使用typename Base<T>::type
代替type
和Base<T>::n
代替n
。您选择的主要是偏好问题。
答案 1 :(得分:1)
在为某些类型Derived
实例化T
之前,编译器无法猜测type
和n
应该来自何处。毕竟,在定义Base
后,为不同类型提供Derived
的专业化是合法的。
您需要改变的是:
template<class T>
struct Derived : Base<T>
{
typename Base<T>::type field; // tell the compiler it's a type,
// and where it comes from
int f() { return Base<T>::n; }// tell the compiler where n comes from too
};
using
声明的工作原理相同,通过限定这些名称,如果您多次使用每个名称,它最终会更清晰。
答案 2 :(得分:0)
您可以通过多种方式执行此操作,如果您希望Derived类自然地使用Base类,您可以尝试使用模板模板。
假设你有相同的基类,那么派生必须看起来像这样:
template< class T, template<typename> class Base >
struct Derived : Base<T>
{
typename Base<T>::type field;
int f()
{
return n;
}
int f(int x)
{
return Base<T>::f(x);
}
};
但要实例化Derived类,您还需要指定Base类。
喜欢这个
Derived<int, Base> object;
现在假设您不希望,您只想从 SAME 基类中实例化Derived对象,然后您必须专门化派生模板。
template< class T, template<typename> class Base = Base >
struct Derived : Base<T>
{
Base<T>::type field;
int f()
{
return n;
}
int f(int x)
{
return Base<T>::f(x);
}
};
这样您现在可以创建Derived<int>
或Derived<string>
int main()
{
Derived<int> bs1;
bs1.field = 200;
std::cout << bs1.f() << std::endl;
std::cout << bs1.f(50)<< std::endl;
std::cout << bs1.field<< std::endl;
Derived<std::string> bs2;
bs2.field = "example";
std::cout << bs2.f() << std::endl;
std::cout << bs2.f(50)<< std::endl;
std::cout << bs2.field<< std::endl;
return 0;
}
当您打算因某种原因切换基类时,可能适用于测试用例。更改基类也可以更改上下文。
您还可以创建一个模板typedef,它允许您将base属性带到您自己的Derived类。这是一个很好的方法。