Archived

This topic is now archived and is closed to further replies.

How come...

This topic is 5401 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

How come when I declare a class with the .h and .cpp, sometimes I have to #include the .cpp at the bottom of my .h file, and sometimes I don''t. My problem, to make it more clear, is when I declare a class with a header and implementation file, when I go to compile and run my program, sometimes I get a bunch of unresolved external errors when it tries to link my .h and .cpp together. To fix the problem, I simply #include the .cpp after the class declaration in the .h file, which I shouldn''t have to, but it fixes the problem. This will clear the problem up until after working on my program some more, and trying to link all the files again, I''ll get the same error as before, and to fix it up this time, I simply remove the #include .cpp from the .h file, then everything works fine again. And this basically just goes back and forth with my removing the .cpp then next time including the .cpp. Does anybody know why this is. I''m using Visual Studio 6, C++, and I''m not using templates or anything like that. I do have the #include .h in the .cpp, and use ifndef blah define blah in both my .h and .cpp. Also, I do not have this problem with just this class, it has happened with others, but does not happen with all of them. Anybody have any ideas? Thanks in advance - Dan He who laughs, lasts

Share this post


Link to post
Share on other sites
You should never #include source (.c, .cpp, .cc, etc.) files - #include is for headers and headers only (and thus, clearly, so are #ifndef/#define/#endif include guards). As for the unresolved externals - care to give some more specific information about the actual problem?

Share this post


Link to post
Share on other sites
All the the unresolved external errors are I get are for the functions of the class that I try to call, such as the constructor, destructor, and any other functions I try and use that are part of the class

- Dan
He who laughs, lasts

Share this post


Link to post
Share on other sites
Also, normally I do "never" include the .cpp files, it''s just that it was the only way I could get my program to work. Oh, except for when I use templates, then you have to either put both the header and implementation in one file, or include the .cpp in the .h for it to work. At least, as far as I know you have to, that''s what my prof told me and it was the only way we could get them to work.

- Dan
He who laughs, lasts

Share this post


Link to post
Share on other sites
I don't use ifndef anymore.
I use:
#pragma once

Write the above line in at least in your header file.
It will force all the files that contain to be included
only once, preventing redefenitions.

You "main" source file should call all the headers of
the classes youre using.

People will bitch about the usage of "#pragma once"
because it only works in visual c++, it isn't supported by
borland, blah blah blah. Just use, if its simpler, use it.

Try it out on all your headers, don't forget to remove
your ifndefs, or it might blow up, and if it still gives an
error come back here and tell us what it is.

[Hugo Ferreira][Positronic Dreams]
Need [3D Artist] & [Sound Designer]
for small project. Contact me plz...



[edited by - pentium3id on March 2, 2003 12:37:10 AM]

Share this post


Link to post
Share on other sites
You should only use inclusion guards ( the #ifndef ... ) in your header files, not in your source-files. This would probably explain why you get unresolved external errors.

pentium3id:
The problem with using #pragma once isn''t that it''s not supported by Borland and others, but that it isn''t Standard, and that a perfectly good Standard alternative exists. You should always do things the standard way if it offers the same functionality.

-Neophyte

Share this post


Link to post
Share on other sites
quote:
Original post by pentium3id
People will bitch about the usage of "#pragma once"
because it only works in visual c++, it isn''t supported by
borland, blah blah blah. Just use, if its simpler, use it.



Actually, if you pay attention to the exact definition of #pragma once, you''ll see that it says the file will not be opened several times. Which doesn''t mean that it won''t be inserted several times.

It is a speed optimization which is orthogonal to the presence of #include guards. Behaviour may change at any time (and has in the past).

If you look at MSVC wizard-generated sources, you''ll notice they usually have both a #pragma once and #include guards (on some random GUID string)

This alone should raise a flag.

There was a discussion on the topic in the Boost mailing list, the most directly relevant post is here.


[ Start Here ! | How To Ask Smart Questions | Recommended C++ Books | C++ FAQ Lite | Function Ptrs | CppTips Archive ]
[ Header Files | File Format Docs | LNK2001 | C++ STL Doc | STLPort | Free C++ IDE | Boost C++ Lib | MSVC6 Lib Fixes ]

Share this post


Link to post
Share on other sites
This is the exact error I get:

Linking...
Connex.obj : error LNK2005: "public: __thiscall CBlock::CBlock(int,int,int,int,int,int,int,int)" (??0CBlock@@QAE@HHHHHHHH@Z) already defined in CBlock.obj
Connex.obj : error LNK2005: "public: __thiscall CBlock::~CBlock(void)" (??1CBlock@@QAE@XZ) already defined in CBlock.obj
Connex.obj : error LNK2005: "public: void __thiscall CBlock::ChangeBlockType(int)" (?ChangeBlockType@CBlock@@QAEXH@Z) already defined in CBlock.obj
Connex.obj : error LNK2005: "public: bool __thiscall CBlock::RotateBlockClockwise(void)" (?RotateBlockClockwise@CBlock@@QAE_NXZ) already defined in CBlock.obj
Connex.obj : error LNK2005: "public: bool __thiscall CBlock::RotateBlockCounterClockwise(void)" (?RotateBlockCounterClockwise@CBlock@@QAE_NXZ) already defined in CBlock.obj
Connex.obj : error LNK2005: "public: bool __thiscall CBlock::MoveBlockLeft(void)" (?MoveBlockLeft@CBlock@@QAE_NXZ) already defined in CBlock.obj
Connex.obj : error LNK2005: "public: bool __thiscall CBlock::MoveBlockRight(void)" (?MoveBlockRight@CBlock@@QAE_NXZ) already defined in CBlock.obj
Connex.obj : error LNK2005: "public: bool __thiscall CBlock::MoveBlockDown(void)" (?MoveBlockDown@CBlock@@QAE_NXZ) already defined in CBlock.obj
Connex.obj : error LNK2005: "public: bool __thiscall CBlock::MoveBlockUp(void)" (?MoveBlockUp@CBlock@@QAE_NXZ) already defined in CBlock.obj
Connex.obj : error LNK2005: "public: bool __thiscall CBlock::MoveEntireBlockToCell(int,int)" (?MoveEntireBlockToCell@CBlock@@QAE_NHH@Z) already defined in CBlock.obj
Connex.obj : error LNK2005: "public: int __thiscall CBlock::ReturnBlockCellRow(void)const " (?ReturnBlockCellRow@CBlock@@QBEHXZ) already defined in CBlock.obj
Connex.obj : error LNK2005: "public: int __thiscall CBlock::ReturnBlockCellColumn(void)const " (?ReturnBlockCellColumn@CBlock@@QBEHXZ) already defined in CBlock.obj
Connex.obj : error LNK2005: "public: int __thiscall CBlock::ReturnBlockStartingCellRow(void)const " (?ReturnBlockStartingCellRow@CBlock@@QBEHXZ) already defined in CBlock.obj
Connex.obj : error LNK2005: "public: int __thiscall CBlock::ReturnBlockStartingCellColumn(void)const " (?ReturnBlockStartingCellColumn@CBlock@@QBEHXZ) already defined in CBlock.obj
Connex.obj : error LNK2005: "public: bool __thiscall CBlock::IsEntireBlockMoveValid(struct sBlock &)const " (?IsEntireBlockMoveValid@CBlock@@QBE_NAAUsBlock@@@Z) already defined in CBlock.obj
Connex.obj : error LNK2005: "public: void __thiscall CBlock:laceEntireBlockOnBoard(int)" (?PlaceEntireBlockOnBoard@CBlock@@QAEXH@Z) already defined in CBlock.obj
Connex.obj : error LNK2005: "public: void __thiscall CBlock::EraseEntireBlockFromBoard(void)" (?EraseEntireBlockFromBoard@CBlock@@QAEXXZ) already defined in CBlock.obj
Connex.obj : error LNK2005: "public: bool __thiscall CBlock::SetBlockCellRow(int)" (?SetBlockCellRow@CBlock@@QAE_NH@Z) already defined in CBlock.obj
Connex.obj : error LNK2005: "public: bool __thiscall CBlock::SetBlockCellColumn(int)" (?SetBlockCellColumn@CBlock@@QAE_NH@Z) already defined in CBlock.obj
Connex.obj : error LNK2005: "public: bool __thiscall CBlock::SetBlockCellStartRow(int)" (?SetBlockCellStartRow@CBlock@@QAE_NH@Z) already defined in CBlock.obj
Connex.obj : error LNK2005: "public: bool __thiscall CBlock::SetBlockCellStartColumn(int)" (?SetBlockCellStartColumn@CBlock@@QAE_NH@Z) already defined in CBlock.obj
Connex.obj : error LNK2005: "public: void __thiscall CBlock::DrawAllBlocks(void)" (?DrawAllBlocks@CBlock@@QAEXXZ) already defined in CBlock.obj
Connex.obj : error LNK2005: "private: void __thiscall CBlock::LoadBlocksIntoBlockData(void)" (?LoadBlocksIntoBlockData@CBlock@@AAEXXZ) already defined in CBlock.obj
Debug/Connex.exe : fatal error LNK1169: one or more multiply defined symbols found
Error executing link.exe.


- Dan
He who laughs, lasts

Share this post


Link to post
Share on other sites
Don''t put the CBlock.cpp file in the CBlock.h file

Insert the CBlock.cpp file put it into your project. The file will compile into an object file which will then be linked with whatever other .cpp files are using the CBlock.h file. They will find the functions defined just once in the CBlock.obj file.

Okay?

Share this post


Link to post
Share on other sites
Thnx for all the replies everyone. The problem was just that I was using the ifndef and define''s in my .cpp as well as my .h''s. Once I took them out of my .cpp file, everything worked fine without the include .cpp in the .h. So winner was Neophyte. Thnx for the solution, and thanks for all the other suggestions from everyone else.

- Dan
He who laughs, lasts

Share this post


Link to post
Share on other sites