为什么模板派生类找不到基类的 ReleaseRows?
数据小陈
结论
ReleaseRows() 是从依赖基类 CRowset<TAccessor> 继承的成员。模板定义中的非限定名称查找不会自动查找依赖基类,因此编译器在定义 ARowset 时找不到这个名称。可以写成 this->ReleaseRows(),也可以在类中添加 using CRowset<TAccessor>::ReleaseRows;。
为什么 C++17 也会报错
示例中的基类类型依赖模板参数 TAccessor:
template <class TAccessor = CAccessorBase>
class ARowset : public CRowset<TAccessor>
编译器解析 ARowset 时,还不知道 TAccessor 最终是什么类型。按照模板的两阶段名称查找规则,编译器会在模板定义处查找 ReleaseRows() 这样的非限定调用。由于名称和参数都不依赖模板参数,编译器不会等到实例化时再从依赖基类中查找它。
这条查找规则在 C++17 和 C++20 中都适用。升级后才出现错误,可能是项目配置或编译器环境发生了变化;仅凭现有信息无法确定具体原因。
修复方法
可以通过 this-> 访问依赖基类成员,并使用完整的基类模板名初始化基类:
#include <atldbcli.h>
template <class TAccessor = CAccessorBase>
class ARowset : public CRowset<TAccessor>
{
HCHAPTER m_hChapter;
public:
ARowset() : CRowset<TAccessor>(), m_hChapter(NULL) {}
HRESULT MoveLast()
{
this->ReleaseRows();
return S_OK;
}
};
也可以在类定义中引入这个基类成员,然后继续使用非限定调用:
template <class TAccessor = CAccessorBase>
class ARowset : public CRowset<TAccessor>
{
using CRowset<TAccessor>::ReleaseRows;
HCHAPTER m_hChapter;
public:
ARowset() : CRowset<TAccessor>(), m_hChapter(NULL) {}
HRESULT MoveLast()
{
ReleaseRows();
return S_OK;
}
};
通常优先使用 this->ReleaseRows(),因为这种写法直接表明该成员来自当前对象的类型层次。
如果修复后仍报错
如果改用 this->ReleaseRows() 后仍无法编译,请检查当前 ATL 版本中的 CRowset<TAccessor> 是否提供了可访问的 ReleaseRows 成员,并确认实际基类是否与示例一致。此时,问题可能已不是依赖基类的名称查找。
备注:内容仅供参考。
