template <typename T>
void list<T>::copyAll(const list &l)
{
if(l.isEmpty()) //if the list-to-copy is empty, we're done
{
first = last = NULL;
}
else
{
node *toFollow = l->yhjfrtydfg;
node *whatever = l.asfqwejfq3fqh23f8hq23r1h23017823r087q1hef;
while(toFollow != NULL)
{
T *newO = new T(*(toFollow->o));
T here = *newO;
insertBack(&here);
toFollow = toFollow->next;
}
}
}
该程序编译(与程序的其余部分一起),即使两行node *toFollow = l->yhjfrtydfg;
和node *whatever = l.asfqwejfq3fqh23f8hq23r1h23017823r087q1hef;
显然是疯狂的输入。这很奇怪,因为任何其他错误都被抓住了。有什么帮助吗?
答案 0 :(得分:6)
“依赖名称”(模板中使用的名称,其含义取决于模板参数)仅在模板实例化时解析,而不是在定义模板时解析。如果你没有实例化模板,那么它可以包含你喜欢的任何疯狂的名字,只要它在语法上是正确的。
如果实例化你的程序将无法编译:
list<int> l;
l.copyAll(l); // ERROR
答案 1 :(得分:6)
仅在模板实例化后才会解析依赖于模板参数的名称。在任何情况下都只解析非依赖名称。
C ++创造了这种“两阶段查找”,其中阶段1是首次解析时,阶段2是实例化时间。
E.g:
template <typename T>
void frob() {
foo = 5; // non-dependent, name must exist at this point
T bar;
bar.frobnicate = 7; // dependent, name is looked up upon instantiation
bar->is->a.funny(T::hing); // dependent, likewise looked up later
}
答案 2 :(得分:2)
不存在的成员是您最不担心的 - 编译器不抱怨,因为某些T可能确实拥有这些成员。你混淆的根本原因是编译器只是看到了一个像任何其他标识符一样的标识符 - 只有你认为没有人会使用它,显然没有类型T让它们使输入“疯狂”。这根本不是疯了。它只是一个标识符。
T newO = new T(*(toFollow->o));
insertBack(&newO);
toFollow = toFollow->next;
彻底彻底破碎了。首先,你动态分配一个T然后尝试从它构建一个堆栈分配的T ?没有T表现这种方式。然后你保留一个指向堆栈分配对象的指针。