定义麻烦。 C ++

时间:2011-07-05 12:52:24

标签: c++ compiler-errors redefinition

这是简化的代码!我有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适用于标题,但我写道它是“伪代码”。我在我的readl项目中使用头文件和cpp文件,只包含头文件,#pragma once在我的标题中。在这个问题中,我只简化了我的代码!请在回答之前阅读所有问题!

*的 EDITED2 * 试图现在编译它。有用。奇怪。

感谢。

3 个答案:

答案 0 :(得分:4)

您不应在C ++中包含.cpp(“代码文件”)。

始终在页眉(.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 :(得分:4)

问题

您不应该在源文件中#pragma once,并且不得#include将文件相互导入。

您的情况下的问题(可能,但您的测试用例并不准确):您#include "Foo.cpp",但此时,编译器在编译{{{}}之前很久就已触发#pragma once 1}}。

简单来说:编译器因为您将源文件与头文件混合而感到困惑。

Canonical modus operandi

  • 每个类的标头/源对

    • 标题通常只有声明,例如Foo.cpp

    • 源包括标题并定义类成员,例如class Foo { void someMethod(); };

  • 其他翻译单元(“源文件”)可以很高兴void Foo::someMethod() {...}标题

实施例

<强> foo.h中

#include

<强> Foo.cpp中

#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

然后,您可以在其他翻译单元中使用此功能:

<强>的main.cpp

#include "foo.h"

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

答案 2 :(得分:1)

适合我:

$ 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文件,没有明显的原因。