因此,假设您有一个递归的基类(例如链表)和派生类。派生类应该重用基类中的构造函数,因为您不想编写冗余代码。你可以尝试一下这个显而易见的事情,它不会起作用:
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;
}
这不起作用 - 当您实例化Derived时,它构造一个Derived实例,然后调用Base类构造函数,该构造函数在Base实例之后抽出Base实例。如果您运行“main”,您将获得:
Derived Base Base Base Base Base
现在,您可以变得聪明并使用类似以下设计模式的东西: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;
}
这通过了测试 - 当我们从Derived的构造函数中回到Base的构造函数时,templating导致Base抽出Derived的实例。整齐!如果你运行main,你会看到以下内容:
Derived Derived Derived Derived Derived Derived
就像你想要的一样!
现在事情变得奇怪了。假设我们希望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;
}
但令人惊讶的是,编译现在因g ++而失败:
X.cpp: In member function ‘void Derived<T>::print()’:
X.cpp:33: error: ‘next’ was not declared in this scope
有谁知道为什么会这样?我几乎怀疑g ++是错的,在这里。我有gcc版本4.3.2和gcc版本4.4.1。
的这个问题答案 0 :(得分:12)
问题是基类Base<T, Derived<T> >
是依赖基类,因为它依赖于模板参数,但next
不是依赖名,因为它不依赖于模板参数。编译器不会在依赖基类中查找非依赖名称。
您可以通过next
访问this->
依赖this->next
来解决此问题:
{{1}}
您可以从C ++ FAQ Lite文章"Why am I getting errors when my template-derived-class uses a member it inherits from its template-base-class?"
中找到更多信息