如何在创建派生类时创建派生类并实例化基类。
喜欢这个
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!
};
您可以使用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
关键字(如我上面所做的那样),以便编译器知道名称引用类型。SO 上有一个问题,其中包含有关此要求的详细信息。
另一种方法是明确限定名称:使用typename Base<T>::type
而不是type
和Base<T>::n
而不是n
。你选择哪一个很大程度上是一个偏好问题。
在你实例化某种类型T
的Derived
之前,编译器无法猜测type
和n
应该来自哪里。毕竟,在定义Derived
后为不同类型的Base
提供专业化是合法的。
您只需要更改:
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
声明的工作方式相同,通过限定这些名称,如果您多次使用每个名称,它最终可能会看起来更干净。
您可以通过多种方式执行此操作,如果您希望派生类自然地使用基类,您可以尝试使用模板模板。
假设您具有相同的基类,则派生必须如下所示:
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<int, Base> object;
现在,假设您不希望这样做,您只想从SAME基类实例化派生对象,那么您必须专门化派生模板。
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,该模板允许您将基属性引入您自己的派生类。这是一个很好的方法。