-1

这是简化的代码!我有 C++ 文件(在哪里实现)和头文件(在哪里是类定义)!

我有一个文件:Foo.cpp包含main.h。我有使用函数 Foo.cpp并且还包括main.h的文件Bar.cpp。它使用 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()

*已编辑* 我知道这#include适用于标题,但我写道它是“伪代码”。我在我的 readl 项目中使用头文件和 cpp 文件,并且只包含头文件并且#pragma once在我的头文件中。在这个问题中,我只简化我的代码!请在回答之前阅读所有问题!

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

谢谢。

4

3 回答 3

4

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

始终在 Header (.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
}

我希望我足够清楚。

于 2011-07-05T12:58:20.767 回答
4

问题

你不应该#pragma once在源文件中,并且你不应该在源文件中#include相互引用。

您的情况下的问题(可能,但您的测试用例不准确):您,但在那一刻,编译器早在 compile#include "Foo.cpp"时就已经触发了。#pragma onceFoo.cpp

简单来说:编译器被混淆了,因为你把源文件和头文件混在一起了。

规范的作案手法

  • 每个类的标头/源对

    • 标头通常只有声明,例如class Foo { void someMethod(); };

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

  • 其他翻译单元(“源文件”)然后可以愉快地#include标头

例子

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
}

然后,您可以在其他翻译单元中使用它,如下所示:

主文件

#include "foo.h"

int main () {
    Foo foo;
    foo.doSomething();
}
于 2011-07-05T12:59:39.240 回答
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 文件。

于 2011-07-05T18:43:47.183 回答