seperating definition and declaration files

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Danigan
    New Member
    • Sep 2007
    • 18

    seperating definition and declaration files

    It's been about 4 years since I did much in C++. To see if I remembered anything, I made a new project, made a header file containing a class, included the header file from my main file, used pointers to dynamically allocate memory for a user-indicated number of class instances, and it was great!

    Now... I used to always be sure to seperate my definition and declaration files. What I have is below and it works, BUT I would like to have three files: main.cpp, animal.h, and animal.cpp. I remember how to code everything. It's the preprocessor directives I cannot seem to get right. However In case a compiler issue arrises, I use Bloodshed's Dev-C++. :-)

    main.cpp:
    Code:
    #include <animal.h>
    ...
    animal.h:
    Code:
    #ifndef ANIMAL_H
    #define ANIMAL_H
    ...
    #endif
    Once I create animal.cpp (already have, but cannot seem to include correctly), do I add a directive to the header file? To the new file?
  • mschenkelberg
    New Member
    • Jun 2007
    • 44

    #2
    I'm not sure what you're asking, but if you want to know if you put a #include"animal .h" in your animal.cpp file, you do...

    Comment

    • Danigan
      New Member
      • Sep 2007
      • 18

      #3
      That's basically what I'm asking, but is seems I must be missing something because I get an error like this for about every member function: "36 C:\Dev-Cpp\practice\mu ltifile classes\animal. h `int animal::animalC ount' previously defined here".

      My header file just has the function prototypes:
      Code:
      //animal.h
      //Class header for the animal class.
      
      //Prevent multiple includes:
      #ifndef ANIMAL_H
      #define ANIMAL_H
      
      //Include dependencies:
      #include <string>
      #include <iostream>
      
      using namespace std;
      
      class animal
      {
      private:    
          static int animalCount; //Total number of animals; Initialized to 0.
          string animalType;
          int animalId;
          
      public:
          animal();
          int getNumberOfAnimals();
      };
      
      #endif
      My animal.cpp is as follows:
      Code:
      //animal.cpp
      
      #ifndef ANIMAL_CPP
      #define ANIMAL_CPP
      
      #include <animal.h>
      
      using namespace std;
      
      int animal::animalCount = 0;
      
      animal::animal()
      {
          cout << "What is the type of this animal? ";
          cin >> animalType;   
          animalCount++;
          animalId = animalCount;
      }
          
      int animal::getNumberOfAnimals()
      {
          return animalCount;
      }    
      
      #endif
      My main.cpp is as follows:
      Code:
      #include <iostream>
      #include <animal.h>
      
      using namespace std;
      
      int main()
      {
          //Initialize a variable to 0 that represents how many animals will be created:
          int totalAnimalsToCreate = 0;
          //Ask the user how many animals are desired:
          cout << "How many animals should we create? " <<endl;
          cin >> totalAnimalsToCreate;
          //Create the user's desired number of animals:
          animal * ptrAnimals = new animal[totalAnimalsToCreate];
          
          cout << ptrAnimals[1].getNumberOfAnimals()
               << " animal(s) created successfully!" << endl;
          system("PAUSE");
          
          delete [] ptrAnimals;
          
          return 0;
      }
      Maybe I've regressed more than I thought or have a rough compiler setting...
      Last edited by Danigan; Oct 17 '07, 09:57 PM. Reason: added main.cpp

      Comment

      • Danigan
        New Member
        • Sep 2007
        • 18

        #4
        This is so common that I can't imagine why I can't find a tutorial on it. Every tutorial does everything in one file for "simplicity ". :-(

        Comment

        • arunmib
          New Member
          • May 2007
          • 104

          #5
          I think the problem is with this line 'int animal::animalC ount = 0;' . It's a private variable and you are intializing it in file just like that......I don't think it's allowed....

          Comment

          • Danigan
            New Member
            • Sep 2007
            • 18

            #6
            Originally posted by arunmib
            I think the problem is with this line 'int animal::animalC ount = 0;' . It's a private variable and you are intializing it in file just like that......I don't think it's allowed....

            I can't do that in the class because it's static. There can only be one instance of it. It only appears once in memory even if I have 50 instances of my class.

            Note that if I copy all the code to the bottom of the header file, it works fine. That means (I think) the code is actually OK. It's my preprocessor directives that must be bad because the code in a separate cpp from the header causes problems.

            Comment

            • Ganon11
              Recognized Expert Specialist
              • Oct 2006
              • 3651

              #7
              First, you have your include statements saying

              [CODE=cpp]#include <animal.h>[/CODE]

              when they should be

              [CODE=cpp]#include "animal.h"[/CODE]

              I think the difference is, when you use <> around the file, you're telling the compiler to look in some standard place first, then anywhere else on the computer. When you use "" around the file, you're telling the compiler to look in the same folder as the current file (which is oftentimes much faster).

              Now, in your main program, you #include animal.h. In your animal.cpp, you #include animal.h. In animal.h, you don't include anything. So your main program will pull this class definition, but where's the method definitions? I'm not entirely sure (because my compiler forces me to put all source code in the same file, so I never have an animal.cpp), but I think you need to #include animal.cpp in the header file.

              Comment

              • Laharl
                Recognized Expert Contributor
                • Sep 2007
                • 849

                #8
                You don't need to include "animal.cpp " because the linker takes care of that for you, as long as the two files have the same name.

                Other than that, this compiles fine for me on g++ 4.1.3...

                Comment

                • Danigan
                  New Member
                  • Sep 2007
                  • 18

                  #9
                  Originally posted by Ganon11
                  First, you have your include statements saying

                  [CODE=cpp]#include <animal.h>[/CODE]

                  when they should be

                  [CODE=cpp]#include "animal.h"[/CODE]

                  I think the difference is, when you use <> around the file, you're telling the compiler to look in some standard place first, then anywhere else on the computer. When you use "" around the file, you're telling the compiler to look in the same folder as the current file (which is oftentimes much faster).

                  Now, in your main program, you #include animal.h. In your animal.cpp, you #include animal.h. In animal.h, you don't include anything. So your main program will pull this class definition, but where's the method definitions? I'm not entirely sure (because my compiler forces me to put all source code in the same file, so I never have an animal.cpp), but I think you need to #include animal.cpp in the header file.
                  I'm not sure what I'm doing is correct, but I manhandled the quotes and brackets in my compiler settings to look in the proper places, haha. It should be unimportant... I think.

                  I completely agree with you that it doesn't seem like I'm pullin in the definitions but there has two opposing considerations:
                  1. If I include the animal.cpp in animal.h, it seems like the compiler would see the declarations before the definitions, causing problems.
                  2. The compiler might not be generating the rediffinition errors unless it indeed can get to the animal.cpp. I imagine it looks there after the animal.h because of the same file name. I thought I remembered that a compiler would look for a file with the same name for the deffinition when you included a header file.

                  Comment

                  • Danigan
                    New Member
                    • Sep 2007
                    • 18

                    #10
                    Uereeeeeka!!

                    I got it!

                    Dev-C++ seems to absolutely require that the deffinitions file for a header have the extension hpp instead of cpp... I'm a little disappointed that Bloodshed would do something so compiler specific, but I suppose it eliminates some ambiguity in file naming.

                    Case closed... (pleased smile)

                    Comment

                    • oler1s
                      Recognized Expert Contributor
                      • Aug 2007
                      • 671

                      #11
                      I do not like what I have seen in this thread so far. The case is not closed as far as I am concerned.

                      Dev-C++ seems to absolutely require that the deffinitions file for a header have the extension hpp instead of cpp.
                      What do you mean by this? I don't like the terminology used. A header file is used for declarations, so are you referring to the header file or the source file that is the companion to the header file? (A source file would contain definitions). Either way, a .h / .cpp scheme works just fine. Dev-C++ is an IDE for MinGW, which in turn is the windows port of gcc. Believe me when I say that it's very, very, very unlikely gcc requires .hpp, as heh, tell that to the entire linux world. And me.

                      I'd like to see the the compiler version. Open up command prompt, go to the directory where Dev-C++ installed all the MinGW executables. Type in g++ -V and post the output here.

                      There also seems to be confusion on the part of what the relationship between include directives, .cpp, and .h files are. And Ganon, I'm very curious as to what compiler you have that requires single files for source code.

                      Question for you people. Why do we have header files, and why do we include them? Well, including them is the rough act of copy and pasting, so here's the big question. Why does the material in header files get copy and pasted at the beginning of source files? What's the reason we need to do so?

                      Take an example:
                      [CODE=cpp]
                      //Also declared in someFunc.h as int someFunc();
                      int someFunc()
                      {
                      ....
                      }
                      [/CODE]

                      [CODE=cpp]
                      //main.cpp
                      int someFunc(); //from an include someFunc.h

                      int main()
                      {
                      ...
                      someFunc();
                      ...
                      }
                      [/CODE]

                      Why do we have a forward declaration in main.cpp? After all, we have the function defined in somefunc.cpp. It's because the compiler deals with source files independently. It will never know about the existence of other source files, even if you tell it to compile multiple files at once. Yet, to compile, you must have valid syntax, which requires knowledge of what you have created in other source files. So the solution are declarations, which do not seek to define what the functions and classes and variables in other source files. Just their existence, so the compiler can compile a source file properly.

                      It is only in the linking stage, that everything gets put together. You leave this up to the linker. It will take all the compiled translation units and create the appropriate binary file from them.

                      Comment

                      Working...