-1

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 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.

HiTECNOLOGYs
  • 327
  • 5
  • 21
  • 1
    Why do you have #pragma once in cpp files? – Alex F Jul 05 '11 at 12:55
  • 10
    **Do not `#include` `.cpp` files.** – Xeo Jul 05 '11 at 12:56
  • I do not do it. I'm cut all unneeded and make my code like pseudocode. Sorry but I thought you'll understand this as I wrote that I have header files and include them at the end but nobody read all question. – HiTECNOLOGYs Jul 05 '11 at 14:05
  • 1
    Hello, @HiTECHNOLOGYs. Your pseudocode is confusing. It would have been much better if you had reduced your actual code to a similarly-sized package and included an actual minimal compilable sample program. For more information about how this would have helped, see http://sscce.org. By the way, the code that *I* wrote based on your description compiles just fine in g++. What compiler do you use? – Robᵩ Jul 05 '11 at 16:42
  • Hello, @Rob. I understand that my code is bad now. I use g++. Witch flags you used? – HiTECNOLOGYs Jul 05 '11 at 18:09
  • I used `g++` with no switches. See my answer. – Robᵩ Jul 05 '11 at 18:44
  • Tbh, I don't see how this is simplified code when you follow really bad and confusing practices there. – Sebastian Mach Jul 06 '11 at 08:14

3 Answers3

4

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.

4

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();
}
Community
  • 1
  • 1
Sebastian Mach
  • 38,570
  • 8
  • 95
  • 130
  • 1
    I prefer #pragma once when using C++, the #ifndef is more C-style for me. Just an opinion :) –  Jul 05 '11 at 13:04
  • 3
    Nothing to do with C. `#pragma once` is a compiler extension (even if it's widely supported). The C++ standard only sanctions the old-style `#ifndef`. – Sebastian Mach Jul 05 '11 at 13:08
  • Downvoter: Don't hide behind your computer screen and take the time to explain. – Sebastian Mach Jul 05 '11 at 13:14
1

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.

Robᵩ
  • 163,533
  • 20
  • 239
  • 308
  • -1: imho, this really needs a disclaimer like "the quick fix would be ... BUT you shouldn't include units of translation into each other" – Sebastian Mach Jul 06 '11 at 08:12
  • @phresnel - there is no "quick fix". The point of my answer is that the OPs code doesn't present the problem about which he complained. Nevertheless, I've added a paragraph per your advice. – Robᵩ Jul 06 '11 at 14:19