Thread: Multiple Definition Error

  1. #1
    Registered User
    Join Date
    Feb 2009
    Posts
    26

    Multiple Definition Error

    I recently started teaching myself C++ from varrious tutorials and books, and once I felt I had a decent understanding of syntax, input, output and classes, I figured I'd try to write a basic text adventure console app.

    The class definition seems to work fine, but I keep getting a "multiple definition" error on the testRoom instance I create, despite the fact that it's only created once.

    At first I thought I might be calling the file twice (I'm keeping the list of rooms in a separate header file), but that is not the case. I've looked online and can't seem to figure out what is wrong with it...

    source.cpp
    Code:
    /*
      Name: Text Adventure
      Copyright: None
      Author: Timothy Sassone
      Date: 14/02/09 22:42
      Description: A basic text adventure engine, written to practice basic C++ skills.
    */
    
    #include <iostream>
    #include <vector> //I plan on using a vector to hold the rooms
    #include <string>
    
    #include "roomDef.cpp"
    #include "roomListing.cpp"
    
    int main() 
    {
        bool quit = 0;
        while(quit==0)
        {
                      //Main loop
                      quit=1;
        }
        
        return 0;
    }
    roomDef.cpp
    Code:
    #ifndef ROOM_DEF //Prevents repeated class definition
    #define ROOM_DEF
    
    #include <iostream>
    #include <string>
    
    using namespace std;
    
    class Room {
          private:
                  string itsName;
                  string itsDesc;
                  
          public:
                 
                 string getName() {
                        return itsName;
                 }                    
                 string getDesc() {
                        return itsDesc;
                 }
                 
                 void setName(string newName) {
                      itsName=newName;
                 }
                 void setDesc(string newDesc) {
                      itsDesc=newDesc;
                 }
                 
                 Room(string name, string desc) { //constructor
                             itsName=name;
                             itsDesc=desc;
                 }
                 ~Room() {}; //Destructor
    };
    
    #endif
    roomListing.cpp
    Code:
    #ifndef ROOM_LIST //Prevents repeat definitions.
    #define ROOM_LIST
    
    #include "roomDef.cpp" //So I have access to the Room class
    
    Room testroom1("1", "2");  //Create two test rooms
    Room testroom2("2", "3");
    
    #endif
    I'm compiling with Dev-C++, and the error it gives is:
    multiple definition of `testroom1'
    first is defined here
    multiple definition of `testroom2'
    first is defined here
    ld returned 1 exit status
    C:\Documents and Settings\Timothy Sassone\Text Adventure\Makefile.win [Build Error] ["Text] Error 1

    Neither of the "first defined here" errors is giving me a line or even file name. Any idea why it is giving me this error?

    Thank you for your time,
    Timothy

  2. #2
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    Do not include cpp files.

    Read this and the section of your text which explains writing header files. If you don't have a book, you really ought to get one.

  3. #3
    Registered User guesst's Avatar
    Join Date
    Feb 2008
    Location
    Lehi, UT
    Posts
    179
    Wow, this is exactly my problem.

    Except that I'm not including the CPP file. I'm only including the .h file and it's still giving me the error.

    Unfortunately the error is way too fast to give a proper example. Lemme try to make a small example.

    util.h
    Code:
    #ifndef UTILS_H_INCLUDED
    #define UTILS_H_INCLUDED
    int someglobalarray[5];
    
    int somefuntionthatusesarray(int foo);
    #endif
    util.cpp
    Code:
    #include <stuff>
    #include "util.h"
    
    int somefuntionthatusesarray(int foo){
      return someglobalarray[foo];
    }
    main.cpp
    Code:
    #include <stuff>
    #include "util.h"
    
    int main () {
      someglobalarray[0] = 1;
      someglobalarray[1] = 2;
      someglobalarray[2] = 3;
      someglobalarray[3] = 4;
      someglobalarray[4] = 5;
    
      return somefuntionthatusesarray(3);
    }
    Okay, obviously I haven't compiled this, but I think it illustrates the problem. If I could compile this I compile this I would get:
    Code:
    -------------- Build: Release in numbrixgenerator ---------------
    
    Linking console executable: bin\Release\whatever.exe
    obj\Release\main.o:main.cpp:(.bss+0x4): multiple definition of `_someglobalarray'
    obj\Release\util.o:utils.cpp:(.bss+0x0): first defined here
    collect2: ld returned 1 exit status
    Process terminated with status 1 (0 minutes, 1 seconds)
    0 errors, 0 warnings
    And no EXE.

    Hu?
    Type-ins are back! Visit Cymon's Games at http://www.cymonsgames.com for a new game every week!

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    The problem is that you are defining someglobalarray in the header, so it is defined in each source file that includes the header. If you really need a global variable to be shared across source files, declare it extern in the header, and define it in exactly one source file.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Your first example was including cpp files, hence whiteflag's response.

    The array someglobalarray is defined in every source file that #include's util.h. If more than one source file does that (and both util.cpp and main.cpp do in your latest example) that array is multiply defined. Which is exactly what your linker is telling you.

    Declare someglobalarray as extern in util.h, and place a definition (without the extern keyword) in exactly one of your source files which #include's that header.

  6. #6
    Registered User
    Join Date
    Feb 2009
    Posts
    26
    I'm currently borrowing a (slightly dated) copy of Sam's Teach Yourself C++ from the local library. However, it's a few years old, and some of the syntax is a bit off. Being one of the early editions, there are a couple typos as well. It's getting the point accross, but I'm have to get most of my syntax help elsewhere. It didn't really explain when/why you use .h instead of .cpp

    Oh well, it works now, thanks everyone!

    Tim

  7. #7
    Registered User guesst's Avatar
    Join Date
    Feb 2008
    Location
    Lehi, UT
    Posts
    179
    Quote Originally Posted by grumpy View Post
    The array someglobalarray is defined in every source file that #include's util.h. If more than one source file does that (and both util.cpp and main.cpp do in your latest example) that array is multiply defined. Which is exactly what your linker is telling you.

    Declare someglobalarray as extern in util.h, and place a definition (without the extern keyword) in exactly one of your source files which #include's that header.
    Ah, thank you, thank you, thank you.

    So like this:
    util.h
    Code:
    #ifndef UTILS_H_INCLUDED
    #define UTILS_H_INCLUDED
    
    extern int someglobalarray[5];
    
    int somefuntionthatusesarray(int foo);
    #endif
    util.cpp
    Code:
    #include <stuff>
    #include "util.h"
    
    int someglobalarray[5];
    
    int somefuntionthatusesarray(int foo){
      return someglobalarray[foo];
    }
    main.cpp
    Code:
    #include <stuff>
    #include "util.h"
    
    int main () {
      someglobalarray[0] = 1;
      someglobalarray[1] = 2;
      someglobalarray[2] = 3;
      someglobalarray[3] = 4;
      someglobalarray[4] = 5;
    
      return somefuntionthatusesarray(3);
    }
    Yes, that seems to get it compiled. Thanks again, you guys, as always, are great.
    Type-ins are back! Visit Cymon's Games at http://www.cymonsgames.com for a new game every week!

  8. #8
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    But you are aware that globals should be avoided, yes?
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  9. #9
    Registered User guesst's Avatar
    Join Date
    Feb 2008
    Location
    Lehi, UT
    Posts
    179
    Quote Originally Posted by Elysia View Post
    But you are aware that globals should be avoided, yes?
    Sigh. Yes mother.

    Thing is I know how I should have done it differently, but at this point a global was a cheaper solution. And it works. Besides, I finally found a use for externs.
    Type-ins are back! Visit Cymon's Games at http://www.cymonsgames.com for a new game every week!

  10. #10
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    No, don't take it as an order. Just take into consideration.
    Easy solutions can easily break when things scale up in complexity.
    It's a suggestion, and an advice, and a question to see if you are aware of the consequences.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. An error is driving me nuts!
    By ulillillia in forum C Programming
    Replies: 5
    Last Post: 04-04-2009, 09:15 PM
  2. Errors including <windows.h>
    By jw232 in forum Windows Programming
    Replies: 4
    Last Post: 07-29-2008, 01:29 PM
  3. Avoiding Global variables
    By csonx_p in forum Windows Programming
    Replies: 32
    Last Post: 05-19-2008, 12:17 AM
  4. more then 100errors in header
    By hallo007 in forum Windows Programming
    Replies: 20
    Last Post: 05-13-2007, 08:26 AM
  5. Problem with Visual C++ Object-Oriented Programming Book.
    By GameGenie in forum C++ Programming
    Replies: 9
    Last Post: 08-29-2005, 11:21 PM