如何在派生实例化之前创建抽象类



如何在创建派生类时创建派生类并实例化基类。

喜欢这个

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而不是typeBase<T>::n而不是n。你选择哪一个很大程度上是一个偏好问题。

在你实例化某种类型TDerived之前,编译器无法猜测typen应该来自哪里。毕竟,在定义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,该模板允许您将基属性引入您自己的派生类。这是一个很好的方法。

最新更新