LNK2019内联函数的未解决错误

LNK2019 unresolved error for inline function

提问人:zeboidlund 提问时间:12/23/2011 最后编辑:A.R.zeboidlund 更新时间:4/15/2021 访问量:4913

问:

我不知道为什么会这样。我得到的错误如下:

Error   2   error LNK2019: unresolved external symbol "public: int __thiscall Graphics::GLMatrix::getColumnSize(void)" (?getColumnSize@GLMatrix@Graphics@@QAEHXZ) referenced in function _SDL_main  C:\Users\holland\Documents\code\c++\projects\OpenGL_01\OpenGL_01\main.obj
Error   3   error LNK2019: unresolved external symbol "public: int __thiscall Graphics::GLMatrix::getRowSize(void)" (?getRowSize@GLMatrix@Graphics@@QAEHXZ) referenced in function _SDL_main    C:\Users\holland\Documents\code\c++\projects\OpenGL_01\OpenGL_01\main.obj
Error   4   error LNK1120: 2 unresolved externals   C:\Users\holland\Documents\code\c++\projects\OpenGL_01\Debug\OpenGL_01.exe  

未链接的是我的 Matrix 类中的 and 函数。我做错了什么?getRowSize()getColumnSize()

那么,我在这里做错了什么?我一直在寻找...以各种方式搜索。

守则

头文件:

#ifndef GLMATRIX_H
#define GLMATRIX_H

#pragma once

#include <array>


namespace Graphics {

    class GLMatrix
    {
    public:
        GLMatrix(int sizeX, int sizeY);
        ~GLMatrix();
        void allocMatrix();
        void addColumnI(int row, int column, long item);
        void revertRowsByColumns(); /*changes the formula of r * c to c * r*/
        GLMatrix &operator *(float scalar); /*multiply by scalar*/
        inline int getRowSize();
        inline int getColumnSize();
    private:
        int _sizeX, _sizeY;
        long** _pArray;
    };

}

#endif //GLMATRIX_H

源:

#include "GLMatrix.h"

namespace Graphics {

    GLMatrix::GLMatrix(int sizeX, int sizeY)
    {
        _sizeX = sizeX; 
        _sizeY = sizeY;
    }

    GLMatrix::~GLMatrix()
    {
        delete _pArray;
    }

    void GLMatrix::addColumnI(int row, int column, long item) {

    }

    inline int GLMatrix::getRowSize() {
        return _sizeX;
    }

    inline int GLMatrix::getColumnSize() {
        return _sizeY;
    }

    void GLMatrix::allocMatrix() {

        _pArray = new long*[_sizeX];

        for (int i = 0; i < _sizeX; ++i) {          
            _pArray[i] = new long[_sizeY];
        }

    }

    void GLMatrix::revertRowsByColumns() {

        long** columns = new long*[_sizeY];

        for (int col = 0; col < _sizeY; ++col) {
            columns[col] = new long[_sizeX];
            memmove(
                columns + col, 
                _pArray[_sizeX - col], 
                sizeof(_sizeX) - sizeof(col)
            );
        }   
    }

}

主要:

#include <SDL.h>
#include "GLMatrix.h"


int main(int argc, char* argv[]) {

    //SDL_Init(SDL_INIT_EVERYTHING);

    //matrix test

    Graphics::GLMatrix* matrix = new Graphics::GLMatrix(3, 3);

    int num_rows = matrix->getRowSize();
    int num_columns = matrix->getColumnSize();
    for (int row = 0; row < num_rows; ++row) {

    }

    //SDL_Quit();

    delete matrix;

    return 0;
}
Visual-C++ 链接器 编译器 错误未解决 - 外部

评论


答:

1赞 Raymond Chen 12/23/2011 #1

内联函数必须在头文件中定义。(更具体地说,定义必须在使用它的每个翻译单元中可见。

评论

2赞 Raymond Chen 12/23/2011
非正式地,翻译单元是单个C++文件及其 #includes 的所有文件
0赞 Hossein 6/5/2012
对于傻瓜:无论您拥有什么头文件,您都不能永远永远不会将内联函数放在一个 .cpp 文件中并从另一个 .cpp 文件中调用它。内联函数必须与调用它们位于同一 .cpp 文件中,或者位于 .h 文件中的某个位置。如果不这样做,你将花费 4 个小时来调试链接器错误,但不会成功。请务必阅读 parashift.com/c++-faq-lite/inline-functions.html
2赞 Vladimir 6/18/2012 #2

必须在头文件中声明内联函数的常识已不再正确。几年来,大多数编译器都实现了一种称为链接时间优化 (gcc) 或链接时间代码生成 (VC) 的功能,该功能保存了有关内联函数(以及其他函数)的重要信息,允许链接器将所有目标文件视为“一个大的快乐翻译单元”。因此,链接器可以内联您放入 cpp 文件中的函数。

相关链接: http://msdn.microsoft.com/en-us/library/xbf3tbeh.aspx http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html (搜索 -flto)

编辑:从我之前写的内容中显然没有理解。此功能并非旨在使懒惰的程序员免于在每个翻译单元中声明内联函数。但它确实会给你带来这种可能导致问题的副产品。 务必在头文件中声明内联函数。

评论

3赞 Pixelchemist 7/17/2013
-1.你声称内联函数不需要在标题中是正确的,但如果它们不在标题中,它们需要在每个翻译单元中。链接时优化/代码生成并不是为每个翻译单元获取定义的方法,因为它使程序的标准符合性取决于编译器选项而不是代码。内联函数需要在每个翻译单元中定义,方法是单独定义它们或通过头文件中的内联定义来定义它们。
0赞 Vladimir 1/15/2014
感谢您的澄清!但我认为你混淆了必须和应该。在这种情况下,我们不应该依赖编译器选项,但它确实有效,并且需要您了解此功能(这就是我最初遇到此问题的方式)。
1赞 Pixelchemist 1/15/2014
不,我不是在混淆必须和应该,但我认为你这样做。我们不能依赖链接时间优化来获得有效的函数定义。在翻译单元中缺少内联函数定义的程序(用于)是不合规的。因此,即使 LTO/LTCG 使它工作,它仍然是错误的,因为如果您依赖这种行为,您甚至可能无法在没有 LTO/LTCG 的情况下编译程序。所以不要这样做。
0赞 Vladimir 1/15/2014
好吧,很公平:)当然,我从不这样做,这就是我在帖子编辑中写的。
1赞 Pixelchemist 7/17/2013 #3

1. 翻译单元是单个源文件(在本例中为“源”和“主”)以及包含的文件。

2. 内联函数

C++11, §3.2/3

"[...]内联函数应在使用 ODR 的每个翻译单元中定义。[...]"

§ 7.1.2/4

内联函数应在使用内联函数的每个翻译单元中定义,并且在每种情况下都应具有完全相同的定义(3.2)。[...]

您的“源”翻译单元的定义是 和 。您的“主要”翻译单元没有!这是未定义的行为,因为编译器不需要检查它。getRowSizegetColumnSize

LTCG/LTO

弗拉基米尔的部分回答是正确的。有链接时间优化(或链接时间代码生成)。但它并不能帮助懒惰的程序员保存内联函数的函数定义。

LTCG/LTO 是为了让编译器同时看到所有函数,而编译器又可能决定内联函数,而这些函数在正常情况下是不可见的。声明的函数必须根据定义在使用它们的每个点上对编译器可见。因此,LTCG/LTO 不需要(也不应被滥用)来解决缺失的内联链路错误。inline


只是为了澄清一下:我很清楚这是一个老问题,但还没有正确回答,我只是摔倒了。

1赞 Sumedha 4/15/2021 #4

我还面临着Visual Studio 2019库中内联函数的链接错误问题。我在 C/C++ 属性的语言选项卡中将属性“删除未引用的代码和数据”设置为“否”并解决了链接错误。