c++ - 基类中的函数名解析
问题描述
考虑以下代码片段,
#include <memory>
template <typename Derived>
class Base
{
public:
int foo()
{
return static_cast<Derived*>(this)->bar(); // I expected a compilation error here
}
private:
int bar()
{
return 1;
}
};
class Derived : public Base<Derived> {};
int baz()
{
return std::unique_ptr<Derived>()->foo();
}
据我了解,模板类Base
将该函数声明bar
为私有,因此即使是Derived
类也不可见,更不用说任何Derived
对象的用户了。
在模板类Base的公共函数foo
中,我尝试bar
通过一个Derived
对象来访问一个不存在的函数。我预计编译器无法找到该函数bar
。
Q. 编译器如何通过对象的使用找到模板类的私有bar
函数?Base
Derived
https://godbolt.org/z/jVxW-k
Derived
现在考虑对其中类不再为空的代码段进行轻微变化。
class Derived : public Base<Derived>
{
private:
int bar()
{
return 1;
}
};
在这里,预期的输出是编译器错误的消息,
<source>: In instantiation of 'int Base<Derived>::foo() [with Derived = Derived]':
<source>:30:44: required from here
<source>:9:49: error: 'int Derived::bar()' is private within this context
9 | return static_cast<Derived*>(this)->bar();
| ^
<source>:22:9: note: declared private here
22 | int bar()
| ^~~
Compiler returned: 1
问:为什么编译器bar
现在无法找到私有函数?有什么方法可以强制派生实现来实现该功能bar
? https://godbolt.org/z/PrkNo6
使用的编译器:g++ 9.2。使用的编译器标志:-std=c++17 -O3 -Wall -Werror
.
提前致谢!!!
解决方案
Q. 编译器如何通过Derived对象找到Base模板类的私有bar函数?
为了
return static_cast<Derived*>(this)->bar();
Derived
没有bar
,
查看基类发现Base::bar
。
我们在Base
范围内,所以我们可以访问Base::bar
(即使应用于其他类型)
Q. 为什么编译器现在找不到私有函数栏?有什么方法可以强制派生实现来实现功能栏?
现在,Derived
有一个bar
, 停止查找。
但Derived::bar
在 的范围内是私有Base
的(即使应用于Derived
实例)。
推荐阅读
- flutter - 处理模型生成按钮的 onPress
- python - 通过快捷方式激活 Python 代码。在数据库中搜索选定的元素
- mysql - 用当前日期时间更新 mysql 行或列数据?
- xml - 如何在 xslt 中将 xs:dateTime 转换为 xs:string
- apache-flink - java.lang.OutOfMemoryError:Apache flink 1.10 中的元空间部署 kubernetes 集群
- html - 高级 Google 搜索引擎查询的 URL 格式
- rabbitmq - Rabbitmq 安装和管理员用户创建
- r - 建立用户活动群组
- java - 与 Gridgain Ignite 版本 8.5.8 和 8.7.13 等效的开源 Apache Ignite 版本
- sql - T-SQL 使用条件对数据进行分组