Visual Studio链接器错误:函数声明与定义参数常量性不一致
这个问题的核心在于C++对函数签名中参数const修饰的区分规则,以及第二个函数的声明与定义签名不匹配,才触发了VS2017的链接错误。
第一个案例:按值传递的顶层const不影响函数签名
当参数是按值传递时,参数类型的顶层const(比如int const,和const int等价)不会被纳入函数签名。因为按值传递时,函数接收的是参数的副本,顶层const只是限制函数内部不能修改这个副本——对外部调用者和链接器来说,void foo(int)和void foo(int const)完全是同一个函数。
这就是第一个例子能正常链接的原因:
// .h 声明 void foo(int); // .cpp 定义 void foo(int const){}
编译器和链接器会判定两者是同一个函数,甚至Clang sanitizer推荐在定义中加上顶层const,这是合理的最佳实践——明确函数内部不会修改参数副本。
第二个案例:引用参数的const是函数签名的必要部分
而你的第二个例子里,第二个参数是std::vector<char const *> const &——这是一个const引用,这里的const属于底层const(修饰的是引用指向的vector对象本身,限制函数不能修改这个vector)。这种情况下,const是参数类型的核心组成部分,会被严格纳入函数签名。
如果你的.cpp文件中的定义没有严格匹配这个签名(比如漏写了const,或者把引用改成了值传递),比如写成:
bool check_required_device_extensions(VkPhysicalDevice physicalDevice, std::vector<char const *> & requiredExtensions) { // 你的实现 }
或者:
bool check_required_device_extensions(VkPhysicalDevice physicalDevice, std::vector<char const *> requiredExtensions) { // 你的实现 }
那么声明和定义的函数签名就完全不一致了。链接器在寻找check_required_device_extensions(VkPhysicalDevice, std::vector<char const *> const &)的定义时,找不到匹配的符号,自然会抛出LNK2019无法解析的外部符号错误。
VS2017的编译器行为完全符合C++标准——引用参数的const必须严格匹配声明与定义的签名。你需要检查.cpp文件中的函数定义,确保第二个参数和头文件声明完全一致:
bool check_required_device_extensions(VkPhysicalDevice physicalDevice, std::vector<char const *> const & requiredExtensions) { // 你的实现代码 }
另外,using namespace std;不会影响类型匹配,问题肯定出在签名的const或引用部分不匹配上。
内容的提问来源于stack exchange,提问作者nikitablack

