Thread: Duplicate definition.

  1. #1
    Registered User
    Join Date
    Aug 2003
    Posts
    15

    Duplicate definition.

    I am missing something obvious here.
    Code:
    #ifndef A_H
    #define A_H
    
    namespace outer
    {
    	namespace inner
    	{
    		class A
    		{
    		private:
    			int aint;
    		public:
    			int getaint(void);
    		};
    
    		A a;
    	}
    }
    #endif // A_H
    So I build a declaration and definition of "a", an object of type A in the outer::inner:: scope.

    Code:
    #include "a.h"
    
    namespace outer
    {
    	namespace inner
    	{
    		int A::getaint(void)
    		{
    			return aint;
    		}
    	}
    }
    Implement the method.

    Code:
    #include <iostream>
    #include <string>
    
    #include "a.h"
    
    int main()
    {
    	std::string x;
    
    	std::cout << outer::inner::a.getaint() << std::endl;
    
    	std::cin >> x;
    
    	return 0;
    }
    Run it.

    No, it doesn't link.

    LNK2005: "class outer::inner::A outer::inner::a" (?a@inner@outer@@3VA@12@A) already defined in prog.obj

    It recognises the type of "a" which is instantiated in the header, yet it claims to find another instance of "a" somewhere. I wondered if it was taking the attempt to invoke the method as a definition rather then an action, but if that was the case, it would surely have created a typeless variable in the outer::inner:: namespace.

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    A is a type name, but a is an object name, that of an object of type A. One solution is to declare a as extern, and then define it in the source file.

    However, if you do not actually need a global variable, do not have one to begin with.
    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

  3. #3
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Never put any variables or objects in header files (unless it's a constant integer). The solution is, as laserlight implies, to put the actual variable or object in a source file and add the name and type of that variable along with extern in the header.
    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.

  4. #4
    Registered User
    Join Date
    Aug 2003
    Posts
    15
    The example I posted is a mercilessly cut down fragment to demonstrate an issue which is cropping up all over an inherited projected consisting of about 70 headers and perhaps 50 source files most stretch for pages, some are encyclopedic in size.

    Yes, a is an object of type A, but there is only a single instance of a. I'm still curious where the duplicate is in my sawn off example.
    Last edited by Exit; 02-26-2008 at 10:58 AM.

  5. #5
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    IF you include that header in several .cpp files, each source file will have an instance of the very same name and type, thus the linker complains because it's not allowed.
    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.

  6. #6
    Registered User
    Join Date
    Aug 2003
    Posts
    15
    But those 3 files I pasted above, if you try to compile them together, no other files, generate the error message I posted.

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Again,
    Code:
    namespace outer
    {
    	namespace inner
    	{
    		A a;
    	}
    }
    The offending line is in the header.
    Put that inside a source file, then do
    Code:
    namespace outer
    {
    	namespace inner
    	{
    		extern A a;
    	}
    }
    In the header.

    Unless you've updated the source and haven't shown us?
    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.

  8. #8
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Each cpp is compiled separately as one compilation unit. Both cpp files include "a.h". Each time you compile a source file that includes "a.h", A a is going to be seen by the compiler. Header guards guard against multiple inclusions from the same compilation unit, but between compiling each source file the compiler "forgets" all defined preprocessor macros.

    As a result the global object a is defined in both object files.

    Solutions have been already suggested.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  9. #9
    Registered User
    Join Date
    Aug 2003
    Posts
    15
    Each cpp is compiled separately as one compilation unit. Both cpp files include "a.h". Each time you compile a source file that includes "a.h", A a is going to be seen by the compiler. Header guards guard against multiple inclusions from the same compilation unit, but between compiling each source file the compiler "forgets" all defined preprocessor macros.

    As a result the global object a is defined in both object files.
    Ah, now THAT answers my question. Cheers.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Errors including <windows.h>
    By jw232 in forum Windows Programming
    Replies: 4
    Last Post: 07-29-2008, 01:29 PM
  2. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM
  3. DLL compiling question
    By Noose in forum Windows Programming
    Replies: 2
    Last Post: 12-16-2004, 07:16 AM
  4. Warnings, warnings, warnings?
    By spentdome in forum C Programming
    Replies: 25
    Last Post: 05-27-2002, 06:49 PM
  5. gcc problem
    By bjdea1 in forum Linux Programming
    Replies: 13
    Last Post: 04-29-2002, 06:51 PM