开发者

Defining trouble. C++

IT'S SIMPLIFIED CODE! I HAVE C++ FILES(WHERE IS IMPLEMENTATION) AND HEADERS FILES(WHERE IS CLASS DEFINITIONS)!

I have a file: Foo.cpp that incliudes main.h. And I have file Bar.cpp that uses funcs Foo.cpp and also includes main.h. It uses struct to access Foo object and call it's function. But struct defined in main.h? I tried to solve it like this:

**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;
    }
};
* * *

But it cause:

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"

What's wrong with my code? Also it's not real code. I simplified my real project and cut all that do not need. Foo.cpp and Bar.cpp of course have their headers where Foo and Bar classes defined and in .cpp files it's only their implementation. Also killAllHumans() called from main.cpp where main() located.

*EDITED* I know that #include works with headers but I wrote that it's "pseudocode". I use header file开发者_C百科 and cpp file in my readl project and include only headers and #pragma once are in my headers. In this question I only simplify my code! Please read all question before answering!

*EDITED2* Tried to compile it now. It works. Strange.

Thanks.


You shouldn't include .cpp ("Code files") in C++.

Always make definintions in the Header (.h) files. You have to create foo.h and bar.h files and then include them into main.h

use .cpp to define the functionality and .h to define the function prototypes as in:

// 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
}

I hope I was clear enough.


Problem

You should not #pragma once in source files, and you shall not #include source files into each other.

The problem in your case (probably, but your test-case is not exact): You #include "Foo.cpp", but at that moment, the compiler has already triggered upon #pragma once long before when compiling Foo.cpp.

In simple terms: The compiler has been confused because you mix up source-files with header-files.

Canonical modus operandi

  • A header/source pair for each class

    • the header generally only has declarations, e.g. class Foo { void someMethod(); };

    • the source includes the header and defines the class members, e.g. void Foo::someMethod() {...}

  • Other translation units ("source files") can then happily #include the header

Example

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
}

Then, you can use this in other translation units like this:

main.cpp

#include "foo.h"

int main () {
    Foo foo;
    foo.doSomething();
}


Works for me:

$ 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) 
$

EDIT: As everyone has pointed out, this program is still very buggy. Not least of which is that it #includes a CPP file for no obvious reason.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜