Определение проблемы. C ++ - PullRequest
0 голосов
/ 05 июля 2011

ЭТО УПРОЩЕННЫЙ КОД!У меня есть файлы C ++ (где это реализация) и файлы заголовков (где определения классов)!

У меня есть файл: Foo.cpp , который включает main.h.И у меня есть файл Bar.cpp , который использует funcs Foo.cpp , а также включает main.h .Он использует struct для доступа к объекту Foo и вызова его функции.Но структура определена в main.h ?Я пытался решить это так:

**IN MAIN.H**
#pragma once

class Foo;
struct FoobarPackage {
    FoobarPackage(Foo *fooObj) {
        soso = fooObj;
    }
    Foo *soso;
};
* * *

**IN FOO.CPP**
#pragma once

#include "main.h"

class Foo {
    void doSomething(bool ololo) {
    if (ololo) //do something else
    }
};
* * *

**IN BAR.CPP**
#pragma once

#include "main.h"
#include "Foo.cpp"

class Bar {
    bool killAllHumans(FoobarPackage planet) {
        planet.soso->doSomething(true);
        return true;
    }
};
* * *

Но это вызвало:

Bar.cpp:8: error: invalid use of incomplete type "struct(WTF??!!! —  author's comment) Foo"
main.h:3: error: forward declaration of "struct(why struct?) Foo"

Что не так с моим кодом?И это не настоящий код.Я упростил свой реальный проект и вырезал все, что не нужно.Foo.cpp и Bar.cpp, конечно, имеют свои заголовки, в которых определены классы Foo и Bar, а в .cpp файлах это только их реализация.Также killAllHumans() вызывается из main.cpp, где находится main().

* EDITED * Я знаю, что #include работает с заголовками, но я написал, что это«псевдокод».Я использую файл заголовка и файл cpp в моем проекте readl и включаю только заголовки, а #pragma once в мои заголовки.В этом вопросе я только упрощаю свой код!Пожалуйста, прочитайте все вопросы, прежде чем ответить!

* EDITED2 * Попытался скомпилировать его сейчас.Оно работает.Странно.

Спасибо.

Ответы [ 3 ]

4 голосов
/ 05 июля 2011

Задача

Вы не должны #pragma once в исходных файлах, и вы не должны #include исходные файлы друг в друга.

Проблема в вашем случае (возможно, но ваш тестовый пример не точен): Вы #include "Foo.cpp", но в этот момент компилятор уже срабатывает на #pragma once задолго до того, как компилируется Foo.cpp.

Проще говоря: Компилятор был сбит с толку, потому что вы смешали исходные файлы с заголовочными файлами.

Канонический образ действий

  • пара заголовок / источник для каждого класса

    • заголовок обычно содержит только объявления, например class Foo { void someMethod(); };

    • источник включает в себя заголовок и определяет членов класса, например void Foo::someMethod() {...}

  • Другие единицы перевода («исходные файлы») могут затем счастливо #include заголовок

* * Пример 1 040 * +1041 *

foo.h

#ifndef FOO_H
#define FOO_H
#pragma once   // note: compiler extension, do as
               //       you prefer, advantage of #pragma 
               //       once is near to nothing on today's
               //       compilers, though

class Foo {
public:
    void someMethod();
};

#endif

foo.cpp

#include "foo.h"

void Foo::someMethod() {
    // do something
}

Затем вы можете использовать это в других единицах перевода, таких как:

main.cpp

#include "foo.h"

int main () {
    Foo foo;
    foo.doSomething();
}
4 голосов
/ 05 июля 2011

Вы не должны включать .cpp ("Файлы кода") в C ++.

Всегда делайте определения в файлах заголовков (.h). Вы должны создать файлы foo.h и bar.h, а затем включить их в main.h

используйте .cpp, чтобы определить функциональность, и .h, чтобы определить прототипы функций, как в:

// foo.h
#pragma once

#include "main.h"

class Foo {
public:
    void doSomething(bool ololo);
};

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

void Foo::doSomething(bool ololo)
{
    if (ololo) //do something else
}

Надеюсь, я был достаточно ясен.

1 голос
/ 05 июля 2011

Работает для меня:

$ cat main.h 
#pragma once

class Foo;
struct FoobarPackage {
    FoobarPackage(Foo *fooObj) {
        soso = fooObj;
    }
    Foo *soso;
};
$ cat Foo.cpp 
#pragma once

#include "main.h"

class Foo {
public:
    void doSomething(bool ololo) {
    if (ololo) ; //do something else
   }
};
$ cat bar.cpp
#pragma once

#include "main.h"
#include "Foo.cpp"

class Bar {
    bool killAllHumans(FoobarPackage planet) {
        planet.soso->doSomething(true);
        return true;
    }
};
$ g++ -c bar.cpp
bar.cpp:1:9: warning: #pragma once in main file
$ $ g++ -v
Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.4.3-4ubuntu5' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --program-suffix=-4.4 --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-plugin --enable-objc-gc --enable-targets=all --disable-werror --with-arch-32=i486 --with-tune=generic --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu
Thread model: posix
gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5) 
$

РЕДАКТИРОВАТЬ : Как отметил каждый , эта программа все еще очень глючит.Не в последнюю очередь это то, что это #include файл CPP без видимой причины.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...