我是C ++的新手。在我的学习阶段,我遇到了以下问题。
我正在尝试从类模板stack
派生一个类Queue
。
编译器在stack
..\src\TrainingDay2.cpp:44:3: error: 'b' was not declared in this scope
b=a;
请帮助找出根本原因。
#include <iostream>
using std::cout;
using std::endl;
template<class T> class Queue //Base class
{
private:
T ArrQueue[20];
protected:
T* a;
T* b;
public:
Queue() { cout<<"QUEUE CONST "<< endl; }
void push(T x);
void pop(void);
};
template <class T>
class stack :public Queue<T> // Derived class
{
public:
stack():Queue<T>() {
b=a;
}
void pop() {
b--;
}
};
int main()
{
stack<int> S;
return 0;
}
答案 0 :(得分:2)
因为基类是一个模板,其实例化取决于派生类的模板参数,并且您试图命名基类的成员,所以要编写两阶段查找{{1 }},而不是this->b
。
(并且不需要默认的构造函数调用。)
b
欢迎使用C ++ ...:P
stack() { this->b = this->a; } void pop() { this->b--; }
在类或类模板的定义中,如果基类依赖于模板参数,则在非限定名称查找期间不会检查基类范围。类模板或成员的定义点,或者在类模板或成员的实例化过程中。 [..]
答案 1 :(得分:2)
原因是在模板内部,适用两阶段名称查找规则:
在定义(=解析)模板时,会查找(=已解析)不依赖于模板参数的名称。
在实例化模板时(当您提供模板参数时)会查找依赖于模板参数的名称。
仅在实例化时的名称查找期间搜索依赖于模板参数的基类。
这种两阶段查找的原因是,在知道模板参数之前,编译器无法知道基类(或其他相关构造)的定义是什么。请记住,模板专业化存在。
您需要以某种方式告诉编译器名称b
是依赖的。你基本上有三种方法可以做到这一点:
使用this->
作为名称的前缀;因为您在类模板中,所有成员都隐式依赖模板参数:
this->b = a;
使用名称的完全限定条件。这将使模板参数的依赖性显式:
Queue<T>::b = a;
将using
声明放入您的类,以通知编译器该名称来自依赖基类:
template <class T>
class stack :public Queue<T> // Derived class
{
protected:
using Queue<T>::b;
public:
stack():Queue<T>()
{
b=a;
}
void pop()
{
b--;
}
};
答案 2 :(得分:0)
在模板定义中,非限定名称将不再找到依赖库的成员(由C ++标准中的[temp.dep] / 3指定)。例如, 您必须使名称依赖,例如通过在它们前面加上这个 - >;
gcc-problem-using-a-member-of-a-base-class-that-depends-on-a-template-argument
是的,它可以在VS中有效。