none
Separating C++ source program into separate files

    Question

  • I have built a fairly complex VS C++ program which works perfectly. My problem is that the single source file is fairly long and, since I am planning to add further features, it would be convenient to separate it into more than one .cpp file. I guess I just don't know the correct procedure for doing this. I wrote a .h file that has all the class definitions etc. in it, but when I break up my source file into, say, two .cpp files and #include the header file in each, the compiler complains about multiple definitions; if I don't #include it, the compiler says it doesn't know what I am talking about. I understand both complaints but don't know how to get out of this situation. I would appreciate some help.

    gabriel weinreich

    Saturday, July 13, 2013 6:30 PM

Answers

  • The "multiple definitions" problem happens if you define a variable or function in the .h file, outside of a class declaration. Move such definitions into a cpp file.  Ideally you should have one h file and one cpp file for each class.

    • Marked as answer by prog.gabi Saturday, July 13, 2013 8:21 PM
    Saturday, July 13, 2013 8:14 PM
  • The usual/best way is one .h file and one .cpp file per class.

    Any file that uses the class must include its header.

    As to your problem, do you have method definitions outside the class definition? If you do, you should either move them to the .cpp file, or use the inline keyword.


    David Wilkinson | Visual C++ MVP

    • Marked as answer by prog.gabi Saturday, July 13, 2013 8:21 PM
    Saturday, July 13, 2013 8:15 PM
  • The definition of a class should not be in a .cpp file.  The member functions could (should?) be but not the class itself. 

    If the variable hr is defined inside a class, it is not an independent variable.  It exists as a member object of a particular instance of that class.  A naked reference to hr in any code other than a member function of that class, either in another class or in a regular function, cannot be resolved.  Since pA by definition points to an instance of the class, pA->hr can be resolved.

    In general, a variable defined outside of any function (and class/structure) is visible to all subsequent functions.  It the variable is defined as static, it is not visible outside that .cpp file.  If not static, it has external linkage and can be referred to by name in another .cpp file after it has been declared external (this is usually done in a header).  A typical sequence is

    a.h
       extern int var;

    a.cpp
       #include "a.h"
       int var = 1;
       void func 1(){...}

    b.cpp
       #include "a.h"
       void func2(){if (a == 1)...}

    Further discussion would probably benefit from some sample code.

    • Marked as answer by prog.gabi Wednesday, July 17, 2013 3:35 PM
    Wednesday, July 17, 2013 1:23 AM
  • ...and of course it's the pointer at the very end that's causing the trouble (it's doubly embarrassing because that's exactly what the linker was telling me had I read the error message more carefully).

    I am not sure, however, how to correct this. I deleted the offending pointer from the .h file and instead inserted

    AudioIO * pMyAudio = new AudioIO();

    as a local variable into every single function that references the class, which worked. But I am wondering whether there is a less laborious (and less memory-consuming) way of doing it. In other words, is there a way of defining "a global within a class"?


    gabriel weinreich

    Never define variables in .h files, just declare them as extern if you want them to be global.

    Do like this in your .h file:

    class AudioIO

    {

    //

    };

    extern AudioIO* pMyAudio;

    Then in just one of your .cpp files do

    AudioIO* pMyAudio = new AudioIO();


    David Wilkinson | Visual C++ MVP

    • Marked as answer by prog.gabi Saturday, July 20, 2013 10:37 AM
    Friday, July 19, 2013 3:13 PM

All replies

  • The "multiple definitions" problem happens if you define a variable or function in the .h file, outside of a class declaration. Move such definitions into a cpp file.  Ideally you should have one h file and one cpp file for each class.

    • Marked as answer by prog.gabi Saturday, July 13, 2013 8:21 PM
    Saturday, July 13, 2013 8:14 PM
  • The usual/best way is one .h file and one .cpp file per class.

    Any file that uses the class must include its header.

    As to your problem, do you have method definitions outside the class definition? If you do, you should either move them to the .cpp file, or use the inline keyword.


    David Wilkinson | Visual C++ MVP

    • Marked as answer by prog.gabi Saturday, July 13, 2013 8:21 PM
    Saturday, July 13, 2013 8:15 PM
  • Thank you both for clear and helpful answers. They solve my problem.

    gabriel weinreich

    Saturday, July 13, 2013 8:23 PM
  • I am reopening this conversation because in the last few days I have completely redone my project and find that there are some basic things I don't understand and can't find answers to. My basic question is this: what exactly is the meaning of the space in a .cpp file before the first function? I thought that any variable defined there becomes a global variable that will be understood by any part of the program. (I know that trying to use globals is generally not a good idea but I am just trying to understand how the compiler views it.) Here is an example: Inside the definition of class A with pointer pA I write

    HRESULT hr;         (1)

    If I now try to use hr inside a different class, the compiler rejects it; but if I refer to it as pA->hr everything is fine. Now if I write the same Eq.(1) at the beginning of a .cpp file, in along the #include statements etc, before the first function, the compiler doesn't mind, yet it is not what I have always called a global variable because if I try to refer to it inside a class function (whether in the same .cpp file or a different one) the compiler doesn't know what I am talking about. So what exactly happens to this quasi-global variable hr in that case? Does it have any existence at all? Is there, in fact, such a thing as a global variable in modern C++? And what can one do in a classless function like main()?

    I apologize for my ignorance, but looking through documentation I just haven't been able to find it. I would appreciate some help.


    gabriel weinreich

    Tuesday, July 16, 2013 11:41 PM
  • The definition of a class should not be in a .cpp file.  The member functions could (should?) be but not the class itself. 

    If the variable hr is defined inside a class, it is not an independent variable.  It exists as a member object of a particular instance of that class.  A naked reference to hr in any code other than a member function of that class, either in another class or in a regular function, cannot be resolved.  Since pA by definition points to an instance of the class, pA->hr can be resolved.

    In general, a variable defined outside of any function (and class/structure) is visible to all subsequent functions.  It the variable is defined as static, it is not visible outside that .cpp file.  If not static, it has external linkage and can be referred to by name in another .cpp file after it has been declared external (this is usually done in a header).  A typical sequence is

    a.h
       extern int var;

    a.cpp
       #include "a.h"
       int var = 1;
       void func 1(){...}

    b.cpp
       #include "a.h"
       void func2(){if (a == 1)...}

    Further discussion would probably benefit from some sample code.

    • Marked as answer by prog.gabi Wednesday, July 17, 2013 3:35 PM
    Wednesday, July 17, 2013 1:23 AM
  • Thank you for a clear exposition of a subject that I (incorrectly) took to be much simpler than it is. It gives me something very useful to work on.

    gabriel weinreich

    Wednesday, July 17, 2013 3:38 PM
  • The last if should be

       if (var==1)

    Thursday, July 18, 2013 1:03 AM
  • Thank you for the correction. I have made all the changes that I understood to be necessary. Incidentally, I have assumed that any preprocessor directives that begin with # -- including not only #include but also #define -- are OK in the space outside any class or function.

    The problem I encounter now is a linker problem, LNK2005, which I am in the process of researching. If I don't find a solution that is clear to me, should I begin another thread? Or should I just continue this thread with another question?


    gabriel weinreich

    Thursday, July 18, 2013 1:14 PM
  • A linker problem is not related to this thread. Start another thread if you have a different question.
    Thursday, July 18, 2013 3:18 PM
  • In your .cpp, the variables you define at the top are visible to your entire .cpp file.
    That's all.
    If you want to define a variable visible by your entire source (all cpp's) you might want to do some research about stdafx.h (to make it simple it is a header file you include in every class header file).


    Thursday, July 18, 2013 4:27 PM
  • I have encountered a problem that I have now spent some time trying to solve but have failed. It is this: I have two major classes, each with its own .cpp and .h, and an extra .cpp file that hold the main() program. Since each of them uses references to both classes, they each need to #include both .h files. The result is that each class finds itself defined three times. The compiler doesn't know this, but the linker raises hell. Is there a good way to solve this other than combining all three .cpp files into one, thus violating the "one .cpp and one .h for each class" rule? Thanks for your help!

    gabriel weinreich

    Thursday, July 18, 2013 11:38 PM
  • Including a h file three places does not define the class three times. But, if you have variables or functions in the h file, but outside of the class definition, that will cause multiple definition linker errors. What have you put in the h file that is outside of the class definition? I.e., outside the {..} of the class definition.

    If you can't see the problem then I suggest you post an h file.

    Friday, July 19, 2013 2:33 AM
  • My face is very red! Here is one of my .h files:

    	class AudioIO
    {
    public:
    	HRESULT LoadData(INT32, BYTE *, INT32);
    	HRESULT ReadData(char *, UINT32*, INT32);
    	HRESULT Initialize(INT32);
    	HRESULT CopyData(BYTE*, UINT32);
    	HRESULT Collapse();
    	HRESULT Finalize(char*);
    	FLOAT *GeneralBuffer, *CollapsedBuffer;
    	UINT32 GeneralBufferSize;
    	UINT32 cycleSize;
    	char *inFileName, *outFileName;
    	UINT32 index;
    	UINT32 settlingIter, takingIter;
    	FLOAT * tempContent;
    }*pMyAudio;
    
    

    and of course it's the pointer at the very end that's causing the trouble (it's doubly embarrassing because that's exactly what the linker was telling me had I read the error message more carefully).

    I am not sure, however, how to correct this. I deleted the offending pointer from the .h file and instead inserted

    AudioIO * pMyAudio = new AudioIO();

    as a local variable into every single function that references the class, which worked. But I am wondering whether there is a less laborious (and less memory-consuming) way of doing it. In other words, is there a way of defining "a global within a class"?


    gabriel weinreich

    Friday, July 19, 2013 1:59 PM
  • ...and of course it's the pointer at the very end that's causing the trouble (it's doubly embarrassing because that's exactly what the linker was telling me had I read the error message more carefully).

    I am not sure, however, how to correct this. I deleted the offending pointer from the .h file and instead inserted

    AudioIO * pMyAudio = new AudioIO();

    as a local variable into every single function that references the class, which worked. But I am wondering whether there is a less laborious (and less memory-consuming) way of doing it. In other words, is there a way of defining "a global within a class"?


    gabriel weinreich

    Never define variables in .h files, just declare them as extern if you want them to be global.

    Do like this in your .h file:

    class AudioIO

    {

    //

    };

    extern AudioIO* pMyAudio;

    Then in just one of your .cpp files do

    AudioIO* pMyAudio = new AudioIO();


    David Wilkinson | Visual C++ MVP

    • Marked as answer by prog.gabi Saturday, July 20, 2013 10:37 AM
    Friday, July 19, 2013 3:13 PM
  • In your .cpp, the variables you define at the top are visible to your entire .cpp file.
    That's all.
    If you want to define a variable visible by your entire source (all cpp's) you might want to do some research about stdafx.h (to make it simple it is a header file you include in every class header file).

    Such variables have external linkage and can be accessed from any other .cpp file if the appropriate extern declaration is visible.

    Defining variables in a .h file is usually a bad idea.

    Friday, July 19, 2013 4:02 PM