G ++ не будет принимать встроенные конструкторы в C ++ - PullRequest
2 голосов
/ 24 ноября 2010

У меня проблема, может быть глупая.

Дело в том, что я не могу встроить конструктор в класс.

Предположим, у меня есть класс с именем Foo.

Если я напишу реализацию Foo примерно так:

class Foo {
  int p;
  public:
    Foo() { p = 1; }
};

или даже так:

class Foo {
  int p;
  public:
    Foo();
};

inline Foo::Foo() {
  p = 1;
}

Программа не будет компилироваться.

Я использую класс, используя стандартный метод:

Foo obj;

Теперь, когда я запускаю g ++ main.cpp foo.cpp, я получаю:

/tmp/ccyVtxvp.o: In function `main':
main.cpp:(.text+0x17): undefined reference to `Foo::Foo()'
collect2: ld returned 1 exit status

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

Есть предположения, почему это происходит?

Ответы [ 7 ]

5 голосов
/ 24 ноября 2010

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

1 голос
/ 24 ноября 2010

Ваша программа компилируется, но не связывается. Скорее всего, вы не включили объектный файл, содержащий определение для класса Foo.

Или, если вы определили это в заголовке, вы просто объявили об этом, но не включили заголовок.

0 голосов
/ 24 ноября 2010

I) При непосредственном построении объекта компилятор старается минимизировать работу и размер объекта. Вот шаги, которые выполняет компилятор:

1) Скомпилируйте main.cpp. Встречает звонок в Foo. В это время компилятор JUST проверяет объявление Foo. Объявление не является встроенным, поэтому оно добавляет в код вызов функции Foo.

2) Компилирует file.cpp (файл, содержащий определение вашего класса). Обратите внимание, что встроенные функции НЕ компилируются (правильно). Они просто расширяются до кода везде, где вызывается функция (при условии, что определение доступно в этом файле).

3) Теперь, когда он пытается соединиться, он не находит определение Foo.

II) При сборке в виде библиотеки компилятор скомпилирует все связанные функции. (Вы можете очень хорошо догадаться, почему). Отсюда и связывание.


Я уверен, что вы знаете, как решить проблему самостоятельно:

class Foo {
  int p;
  public:
    inline Foo() { p = 1; };
};

но предположим, что вам просто интересно, почему различное поведение при создании прямого объекта и построении библиотеки.

0 голосов
/ 24 ноября 2010

Проблема в следующем:

/ tmp / ccyVtxvp.o: в функции main': main.cpp:(.text+0x17): undefined reference to Foo :: Foo () 'collect2: ld возвращен 1 статус выхода

Я предполагаю, что у вас есть класс, определенный в foo.cpp, и вы пытаетесь использовать его в main.cpp. Как уже говорили другие, C ++ не знает, как использовать Foo или даже его существование, если вы не объявили его ранее. Управление модулями в C ++ довольно сложное и примитивное. Возможно, вы склонны к другим более современным языкам программирования, таким как C # или Java.

Создать foo.h:

// foo.h
class Foo:
int p;
public:
    Foo() { p = 1; }
};

Все методы, которые вы определяете в объявлении класса, автоматически считаются встроенными. Как глупое правило, вы должны создать файл .cpp (foo.cpp), соответствующий каждому объявлению или файлу интерфейса (foo.h). В этом случае это бесполезно, так как ваш полный класс находится в файле интерфейса. Но, вероятно, ваш класс будет усложняться, и в конечном итоге вам понадобится определение метода в вашем cpp. Итак:

Создать foo.cpp:

// foo.cpp
#include "foo.h"

Теперь в main.cpp вы можете использовать Foo, , включив его объявление . Это обязательно в C ++:

Создать main.cpp:

// main.cpp

#include "foo.h"

#include <cstdlib>
#include <cstdio>

int main()
{
    Foo f;
    std::printf( "Foo was created\n" );

    return EXIT_SUCCESS;
}
0 голосов
/ 24 ноября 2010

Здесь

inline Foo::Foo() {
     p = 1;
}

удалить inline. Добавьте его в декларацию (в шапку)

Я не уверен, почему это работает, но работает. У меня была та же проблема, и это решило ее.


EDIT: как то так:


class Foo {
  int p;
  public:
  //vvvvvv
    inline Foo();
};

Foo::Foo() {
  p = 1;
}
0 голосов
/ 24 ноября 2010

Я предполагаю, что что-то берет адрес Foo::Foo().Это заставит компилятор ожидать, что где-нибудь будет существовать не встроенная версия.

0 голосов
/ 24 ноября 2010

Вы не упомянули, что находится в заголовочном файле, а что в cpp.

Мне кажется, что вы на самом деле не скомпилировали Foo :: Foo. Это может произойти, когда вы используете строчные.

...