关于类型的内部/外部链接的疑问及编译警告原因咨询
关于类型的内部/外部链接的疑问及编译警告原因咨询
你好!这个问题戳中了C++里一个容易被忽略的知识点——类型也存在内部/外部链接属性,我来帮你理清警告的原因和解决办法:
首先,你提到只了解变量、对象的链接属性,其实像结构体、枚举、typedef定义的类型这类自定义类型,同样有链接属性之分。
GCC抛出的-Wsubobject-linkage警告,核心问题在于:
‘ShaderModuleObject’ has a field ‘GFXAPIShaderModuleHandle ShaderModuleObject::handle’ whose type has internal linkage [-Wsubobject-linkage]
简单来说,你的ShaderModuleObject类是外部链接类型(也就是可以被其他编译单元访问),但它的成员handle的类型GFXAPIShaderModuleHandle是内部链接类型——这个类型只能在当前编译单元中被识别,其他编译单元看不到它。
哪些情况会让类型成为内部链接?
常见的场景有两种:
- 该类型定义在匿名命名空间中;
- 用
static修饰的typedef类型(不过C++里static对typedef的作用更多是限制作用域,匿名命名空间是更常见的触发内部链接的原因)。
为什么这会触发警告?
如果其他编译单元需要使用ShaderModuleObject,它们能看到这个类的定义,却无法识别GFXAPIShaderModuleHandle这个成员类型,这会导致链接阶段出现类型不匹配,甚至引发运行时的未定义行为,GCC的警告就是提前帮你规避这个风险。
解决办法
你可以根据代码的设计需求二选一:
- 让
GFXAPIShaderModuleHandle变为外部链接类型:把它的定义移出匿名命名空间,或者去掉限制其作用域的内部链接修饰,确保所有用到ShaderModuleObject的编译单元都能识别这个类型; - 让
ShaderModuleObject也变为内部链接类型:如果GFXAPIShaderModuleHandle确实不需要对外暴露,那把ShaderModuleObject也放到同一个匿名命名空间中,让它和成员类型都只在当前编译单元可见,消除跨单元的可见性冲突。
你可以检查下代码里GFXAPIShaderModuleHandle的定义位置,调整后就能解决这个警告啦!
备注:内容来源于stack exchange,提问作者Zebrafish
相关产品推荐
相关产品推荐

