Ошибки включения файла (C ++): неопределенная ссылка на ______ - PullRequest
7 голосов
/ 05 января 2012

Всякий раз, когда я компилирую что-то, что включает в себя определенный пользователем класс, я получаю такие ошибки компиляции, которые всегда выглядят так: main.cpp: undefined reference to Complex::Complex(double, double)

Я свел проблему к набору из трех чрезвычайно простых файлов:main.cpp, и, например, Complex.h и Complex.cpp.Я все еще получаю неопределенные ошибки ссылки.Я разрабатываю в Code :: Blocks в Windows, но я получаю то же самое, используя g ++ в Ubuntu.Почему это происходит?Я пытался создать Complex.cpp до main.cpp в Code :: Blocks, и я пробовал g++ main.cpp Complex.cpp столько же, сколько g++ main.cpp.Одни и те же ошибки каждый раз.

/*======== main.cpp ========*/
#include "Complex.h"

int main()
{
    Complex A(1.0, 1.0);
    return 0;
}

/*======== Complex.h ========*/
#ifndef _COMPLEX_H
#define _COMPLEX_H

class Complex
{
    public:
    double x, y;
    Complex(double real, double imag);
};

#endif

/*======== Complex.cpp ========*/
#include "Complex.h"

Complex::Complex(double real, double imag)
{
    x = real;
    y = imag;
}

ed: теперь я получаю разные ошибки, поэтому я должен делать что-то совершенно неправильно.Используя тот же код, что и выше, я получаю:

main.cpp: in function 'int main()':
main.cpp:5:5: error: 'Complex' was not declared in this scope
main.cpp:5:13: error: expected ';' before 'A'

Это странно.Все работало раньше, когда у меня был класс в файле .cpp, но это «плохая практика», поэтому я переместил свои определения классов в файлы .h и сохранил реализацию в файлах .cpp, и теперь ничего не работает.

Ответы [ 2 ]

7 голосов
/ 05 января 2012

Это не ошибка компиляции, это ошибка ссылки.Вы должны убедиться, что связали все свои объекты вместе.Вы можете сделать это несколькими способами:

g++ main.cpp Complex.cpp

Должно работать нормально (и здесь, когда я пытался с вашим примером).Вы также можете сделать это по шагам:

g++ -c main.cpp
g++ -c Complex.cpp
g++ main.o Complex.o
1 голос
/ 05 января 2012

Пока мы остаемся в неведении, является ли это реальным кодом (вероятно, не так, как он работает для нескольких других), давайте немного прокомментируем сам код ... (это не повлияет на ошибку компоновщика )

  1. Имена, начинающиеся с подчеркивания, за которым следует заглавная буква, например, _COMPLEX_H, зарезервированы для реализации компилятора C ++ и стандартной библиотеки C ++. Не используйте их.
  2. Лучше всего создавать переменные-члены private. Редко возникает необходимость сделать фактический элемент данных public (иногда целесообразно сделать нефункциональные элементы public, например, класс событий, где пользователи могут подписываться на обратные вызовы, но они обычно ведут себя как функции, хотя они являются технически объектами) .
  3. Инициализация лучше всего выполняется в списке инициализаторов членов. То есть конструктор будет выглядеть примерно так:

    Комплекс :: Комплекс (двойное реальное, двойное изображение): х (реальный), у (емк) { }

В заключение несколько предположений о том, что не так с реальным кодом, чтобы вызвать проблему с линковкой:

  1. Конструктор определен как inline. Очевидно, это не сработает, если не будет видно определение, где используется конструктор.
  2. Объявление Complex каким-то образом превратило его в безымянное пространство имен, и, таким образом, определение определило класс, отличный от того, который видит main.cpp.
...