سؤال

I have no idea why this is happening. The error I get is the following:

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  

What isn't being linked is a getRowSize() and getColumnSize() function from my Matrix class. What am I doing wrong?

So, what am I doing wrong here? I've been searching...searching every which way.

The Code

Header file:

#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

Source:

#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)
            );
        }   
    }

}

Main:

#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;
}
هل كانت مفيدة؟

المحلول

The common knowledge that inline function MUST be declared in the header file is no longer true. Since several years, most compilers implement a feature called Link Time Optimization (gcc) or Link Time Code Generation (VC) that save important information about inline functions (among others) allowing the linker to look at all the object files as "one big happy translation unit". Thus the linker can inline functions you put in a cpp file.

Relevant links: http://msdn.microsoft.com/en-us/library/xbf3tbeh.aspx http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html (search for -flto)

Edit: It was apparently not understood from what I wrote earlier. This feature was not designed to save lazy programmers from declaring inline functions in each translation unit. But it does give you this byproduct that can cause problems. Do declare inline functions in the header file.

نصائح أخرى

Inline functions must be defined in header files. (More specifically, the definition must be visible in every translation unit in which it is used.)

1. A translation unit is a single source file ("Source" and "Main" in your case) together with the included files.

2. Inline functions

C++11, §3.2/3

"[...] An inline function shall be defined in every translation unit in which it is odr-used. [...]"

§ 7.1.2/4

An inline function shall be defined in every translation unit in which it is odr-used and shall have exactly the same definition in every case (3.2). [...]

Your "Source" translation unit has a definition of getRowSize and getColumnSize. Your "Main" translation unit has not! This is undefined behaviour since the compiler is not required to check for that.

LTCG/LTO

Parts of Vladimir's answer are correct. There is link time optimization (or link time code generation). But it doesn't serve the purpose of helping lazy programmers to save function-definitions for inline functions.

LTCG/LTO is done to make all functions visible to the compiler at once, which in turn may decide to inline function which aren't visible to it under normal circumstances. Functions declared inline must per definition visible to the compiler at every point they are used at. Therefore, LTCG/LTO is not needed for (and should not be abused for the purpose of) solving missing inline link errors.


Just to make things clear: I'm well aware of the fact that this is an old question but it isn't answerd correctly yet and I just fell over it.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top