gpt4 book ai didi

c++ - 为什么我可以从派生类调用基模板类方法

转载 作者:可可西里 更新时间:2023-11-01 18:29:29 25 4
gpt4 key购买 nike

我决定测试“Effective C++”中的示例之一,但没有得到预期的结果。所以,显然这个(简化的)代码不应该编译:

template <class T>
struct A {
void f(){}
};

template <class T>
struct B : public A <T> {
void f2() { f(); } // calling base function - will not compile
};

这是解释(为简单起见更改了类名):

The code above won't compile, at least not with conformant compilers. Such compilers will complain that f doesn't exist. We can see that f is in the base class, but compilers won't look for it there.

We need to understand why. The problem is that when compilers encounter the definition for the class template B, they don't know what class it inherits from. Sure, it's A<T>, but T is a template parameter, one that won't be known until later (when B is instantiated). Without knowing what T is, there's no way to know what the class A<T> looks like. In particular, there's no way to know if it has a f function.

我的编译器 (Visual Studio) 不介意...它甚至不显示任何警告。

以上代码是否正确?

最佳答案

template <class T>
struct A {
void f(){}
};

template <class T>
struct B : public A <T> {
void f2() { f(); } // calling base function - will not compile
};

在派生模板中,表达式 f()不依赖于任何模板参数,因此编译器会尝试在第一阶段查找期间解析它。此时,模板还没有用类型实例化,编译器不会查看基类A<T>。 .原因是编译器不可能知道实例化的类型是否有 A<T> 的特化。可能不包含任何成员。

解决方案是使表达式依赖,最简单的方法是用 this-> 限定:

template <typename T>
void B<T>::f2() { this->f(); }

由于表达式现在是依赖的,查找被延迟到第二阶段,其中类型被替换并且 A<T>是具体类型。另一种选择是使用定义它的类进行限定:

template <typename T>
void B<T>::f2() { A<T>::f(); }

表达式再次变得依赖并将在第二阶段解决。主要区别在于,在第二种情况下,调用是合格的,因此它不使用动态调度。如果A<T>::f()是虚拟的,它仍然会执行 A<T>::f() ,而不是最终的替代者。


代码是否正确?没有。VS接受吗?是的。

这是 Visual Studio 编译器中一个已知的不符合项,它没有实现两阶段查找。它将模板内的所有查找延迟到第二阶段,此时查找成功。

关于c++ - 为什么我可以从派生类调用基模板类方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19128796/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com