LNK2019 неразрешенная ошибка для встроенной функции - PullRequest
2 голосов
/ 23 декабря 2011

Понятия не имею, почему это происходит.Я получаю следующую ошибку:

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  

Что не связано, так это функции getRowSize() и getColumnSize() из моего класса Matrix.Что я делаю не так?

Итак, что я здесь делаю не так?Я искал ... искал в разные стороны.

Код

Заголовочный файл:

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

Ответы [ 3 ]

1 голос
/ 17 июня 2012

Общеизвестно, что встроенная функция ДОЛЖНА быть объявлена ​​в заголовочном файле, больше не соответствует действительности. Уже несколько лет большинство компиляторов реализуют функцию под названием Link Time Optimization (gcc) или Link Time Code Generation (VC), которая сохраняет важную информацию о встроенных функциях (среди прочих), позволяя компоновщику рассматривать все объектные файлы как «одно большое счастье переводческий блок ". Таким образом, компоновщик может встроить функции, которые вы поместили в файл cpp.

Соответствующие ссылки: http://msdn.microsoft.com/en-us/library/xbf3tbeh.aspx http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html (поиск -flto)

Редактировать: Очевидно, это не было понято из того, что я написал ранее. Эта функция не предназначена для того, чтобы избавить ленивых программистов от объявления встроенных функций в каждом модуле перевода. Но это дает вам этот побочный продукт, который может вызвать проблемы. Объявляйте встроенные функции в заголовочном файле.

1 голос
/ 17 июля 2013

1. Единицей перевода является один исходный файл («Источник» и «Основной» в вашем случае) вместе с включенными файлами.

2. Встроенные функции

C ++ 11, §3.2 / 3

"[...] Встроенная функция должна быть определена в каждой единице перевода, в которой она используется odr. [...]"

§ 7.1.2 / 4

Встроенная функция должна быть определена в каждой единице перевода, в которой она используется odr, и должна иметь точно такое же определение в каждом случае (3.2). [...]

Ваша единица перевода "Источник" имеет определения getRowSize и getColumnSize. Ваш "Главный" переводчик не имеет! Это неопределенное поведение, так как компилятор не обязан проверять это.

LTCG / LTO

Части ответа Владимира верны. Существует оптимизация времени ссылки (или генерация временного кода ссылки). Но это не помогает ленивым программистам сохранять определения функций для встроенных функций.

LTCG / LTO делается для того, чтобы все функции были видны компилятору одновременно, который, в свою очередь, может принять решение о встроенной функции, которая не видна ему в нормальных условиях. Объявленные функции inline должны по определению быть видимыми для компилятора в каждой точке, в которой они используются. Следовательно, LTCG / LTO не требуется (и не следует злоупотреблять с целью) устранения недостающих ошибок встроенного канала.


Просто чтобы прояснить ситуацию: я хорошо осознаю тот факт, что это старый вопрос, но на него пока нет правильного ответа, и я просто упал.
1 голос
/ 23 декабря 2011

Встроенные функции должны быть определены в заголовочных файлах.(Более конкретно, определение должно быть видно в каждой единице перевода, в которой оно используется.)

...