use*_*493 6 c++ recursion inheritance templates compilation
所以,假设您有一个递归的基类(例如链表)和派生类.派生类应该重用基类中的构造函数,因为您不想编写冗余代码.你可以尝试一下这个显而易见的事情,它不会起作用:
class Base {
public:
Base(int size) {
if (size <= 0) { next = NULL; }
else { next = new Base(size - 1); }
}
void print() {
cout << " Base ";
if (next != NULL) { next->print(); }
}
protected:
Base *next;
};
class Derived: public Base {
public:
Derived(int size) : Base(size) {}
void print()
{
cout << " Derived ";
if (next != NULL)
{ next->print(); }
}
};
int main()
{
Derived d2(5);
d2.print();
cout << "\n";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这不起作用 - 当您实例化Derived时,它构造一个Derived实例,然后调用Base类构造函数,该构造函数在Base实例之后抽出Base实例.如果您运行"main",您将获得:
Derived Base Base Base Base Base
Run Code Online (Sandbox Code Playgroud)
现在,您可以变得聪明并使用以下设计模式:http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern,它将解决您的所有问题.看看以下非常简洁的代码:
template <class targetT, class recursiveT>
class Base {
public:
Base(targetT size) {
if (size <= 0) { next = NULL; }
else { next = new recursiveT(size - 1); }
}
void print() {
cout << " Base ";
if (next != NULL)
{ next->print(); }
}
protected:
recursiveT *next;
};
class Derived: public Base<int, Derived> {
public:
Derived(int size) : Base<int, Derived>(size) {}
void print()
{
cout << " Derived ";
if (next != NULL)
{ next->print(); }
}
};
int main()
{
Derived d1(5);
d1.print();
cout << "\n";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这通过了测试 - 当我们从Derived的构造函数回到Base的构造函数时,templating导致Base抽出Derived的实例.整齐!如果你运行main,你会看到以下内容:
Derived Derived Derived Derived Derived Derived
Run Code Online (Sandbox Code Playgroud)
就像你想要的一样!
现在事情变得奇怪了.假设我们希望Base和Derived自己模仿; 说它们是链表,我们希望它们保存任意数据.
所以我们可以进一步推动这个:
template <class targetT, class recursiveT>
class Base {
public:
Base(targetT size) {
if (size <= 0) { next = NULL; }
else { next = new recursiveT(size - 1); }
}
void print() {
cout << " Base ";
if (next != NULL)
{ next->print(); }
}
protected:
recursiveT *next;
};
template <class T>
class Derived: public Base<T, Derived<T> > {
public:
Derived(int size) : Base<T, Derived<T> >(size) {}
void print()
{
cout << " Derived ";
if (next != NULL)
{ next->print(); }
}
};
int main()
{
Derived<int> d1(5);
d1.print();
cout << "\n";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但令人惊讶的是,编译现在因g ++而失败:
X.cpp: In member function ‘void Derived<T>::print()’:
X.cpp:33: error: ‘next’ was not declared in this scope
Run Code Online (Sandbox Code Playgroud)
有人知道为什么会这样吗?我几乎怀疑g ++是错的,在这里.我有gcc版本4.3.2和gcc版本4.4.1的这个问题.
Jam*_*lis 12
问题是基类Base<T, Derived<T> >是依赖基类,因为它依赖于模板参数,但next不是依赖名,因为它不依赖于模板参数.编译器不会在依赖基类中查找非依赖名称.
您可以next通过以下方式访问它来解决此问题this->:
this->next
Run Code Online (Sandbox Code Playgroud)
您可以从C++ FAQ Lite文章中找到更多信息,"当我的模板派生类使用从模板基类继承的成员时,为什么会出现错误?"