Include Help Needed
-
Steen Krogsgaard wrote: Are you absolutely sure that your problems stems from multiple inclusions of the classA header? I'll say I'm 95% sure that's the cause. All the linking errors mentioned Class A name in the error field. But now I have a new problem. I took Dave Crow's advice and redid my
#ifndef
statements. Now I'm testing in the class header file if an appropriate preprocessor tag has been defined, if not then it defines it and it continues to have the class declared. If it already has, it skips it. After the initial#ifndef
I use separate ones to test for any required includes for that class. For example, Class A looks like this:#ifndef CLASS_B_INC #define CLASS_B_INC #pragma once #ifndef CLASS_A_INC #include "CLASS_A.h" #endif //Rest of Class here #endif
I think part of my problem was that I was possibly defining the pre-processor tags multiple times. This way, they only get defined in that class' header file. Note here that Class B won't try to define CLASS_A_INC ( that's left to Class A to do ) it will just include it and when that does Class A will define it on its own. Now something like that written above is in all .h files. The .cpp files only have#ifndef CLASS_A_INC #include "CLASS_A.h" #endif
for their own classes, so above would be the Class A .cpp file. Now I'm getting errors that certain elements can't be found such as "cout : undeclared identifier" and "Class E : undeclared identifier" so some of my#include
statements aren't being processed and I don't know why. ________________________________________________________________________ The question "Do computers think?" is the same as "Can submarines swim?" Signature Red Studios JerythJeryth wrote: I'll say I'm 95% sure that's the cause. All the linking errors mentioned Class A name in the error field. Multilple includes will give compiler errors(error C2011: 'CClassA' : 'class' type redefinition), not linking errors! Cheers Steen. "To claim that computer games influence children is ridiculous. If Pacman had influenced children born in the 80'ies we would see a lot of youngsters running around in dark rooms eating pills while listening to monotonous music"
-
Jeryth wrote: I'll say I'm 95% sure that's the cause. All the linking errors mentioned Class A name in the error field. Multilple includes will give compiler errors(error C2011: 'CClassA' : 'class' type redefinition), not linking errors! Cheers Steen. "To claim that computer games influence children is ridiculous. If Pacman had influenced children born in the 80'ies we would see a lot of youngsters running around in dark rooms eating pills while listening to monotonous music"
You're right, I mis-labeled my problem. All classes compiled fine, they just wouldn't link. It was complaining about resolving an exxternal link error or somthing along those lines. ________________________________________________________________________ The question "Do computers think?" is the same as "Can submarines swim?" Signature Red Studios Jeryth
-
I would recommend that you *only* use the #ifndef/#define/#endif in the header file, and that you put only *one* construct for the entire file, as in
// in class_b.h: ifndef CLASS_B_INC #define CLASS_B_INC #pragma once #include "CLASS_A.h" //Rest of Class here #endif // in class_a.h: ifndef CLASS_A_INC #define CLASS_A_INC #pragma once class A : ..... { ... } #endif
You don't need to put #ifndef/#endif around the #include statement in class_b.h. If class_a.h has already been parsed CLASS_A_INC will be defined and it won't be parsed again (it will be an empty file as the preprocessor will remove everything between #ifndef/#endif, and here that means everything in class_a.h), and you will effectively include an empty file. This, IMHO, is much cleaner than putting #ifndef/#endif around every single #include statement in your project. Are you still sure that #pragma once does not solve your problem by itself, i.e. without all the #ifndef/#endif stuff? It does for me. I think MS put #if !defined/#endif for backwards-compatibility reasons (i.e. _MSC_VER <= 1000) Cheers Steen. "To claim that computer games influence children is ridiculous. If Pacman had influenced children born in the 80'ies we would see a lot of youngsters running around in dark rooms eating pills while listening to monotonous music"Okay so I changed those and it cleared up some of the mess. But the old errors came back. In the errors below, CABLE is what I've been referring to as Class A and TABLE is Class F, the bottom tier one. error LNK2019: unresolved external symbol "public: __thiscall CABLE::~CABLE(void)" (??1CABLE@@QAE@XZ) referenced in function "public: __thiscall TABLE::TABLE(int)" (??0TABLE@@QAE@H@Z) error LNK2019: unresolved external symbol "public: __thiscall CABLE::~CABLE(void)" (??1CABLE@@QAE@XZ) referenced in function __unwindfunclet$??0CARD@@QAE@XZ$0 Looks like it doens't know where to go for CABLE function calls. Any ideas? ________________________________________________________________________ The question "Do computers think?" is the same as "Can submarines swim?" Signature Red Studios Jeryth
-
Okay so I changed those and it cleared up some of the mess. But the old errors came back. In the errors below, CABLE is what I've been referring to as Class A and TABLE is Class F, the bottom tier one. error LNK2019: unresolved external symbol "public: __thiscall CABLE::~CABLE(void)" (??1CABLE@@QAE@XZ) referenced in function "public: __thiscall TABLE::TABLE(int)" (??0TABLE@@QAE@H@Z) error LNK2019: unresolved external symbol "public: __thiscall CABLE::~CABLE(void)" (??1CABLE@@QAE@XZ) referenced in function __unwindfunclet$??0CARD@@QAE@XZ$0 Looks like it doens't know where to go for CABLE function calls. Any ideas? ________________________________________________________________________ The question "Do computers think?" is the same as "Can submarines swim?" Signature Red Studios Jeryth
Jeryth wrote: Looks like it doens't know where to go for CABLE function calls No, it looks like it doesn't know where to go for CABLE::~CABLE(void), i.e. the destructor of your CABLE class. Did you perhaps by any chance forgot to define it?:rolleyes: It looks as it's declared in the class allright but not defined in a cpp file. I wonder why you're calling CABLE::~CABLE in TABLE's constructor, looks to me as inefficient member variabel initialization ;) Cheers Steen. "To claim that computer games influence children is ridiculous. If Pacman had influenced children born in the 80'ies we would see a lot of youngsters running around in dark rooms eating pills while listening to monotonous music"
-
Jeryth wrote: Looks like it doens't know where to go for CABLE function calls No, it looks like it doesn't know where to go for CABLE::~CABLE(void), i.e. the destructor of your CABLE class. Did you perhaps by any chance forgot to define it?:rolleyes: It looks as it's declared in the class allright but not defined in a cpp file. I wonder why you're calling CABLE::~CABLE in TABLE's constructor, looks to me as inefficient member variabel initialization ;) Cheers Steen. "To claim that computer games influence children is ridiculous. If Pacman had influenced children born in the 80'ies we would see a lot of youngsters running around in dark rooms eating pills while listening to monotonous music"
Yeah, saw the destructor reference and that was the first thing I checked before I posted. If only it would have been so easy. I'm not explicitly calling for any CABLEs to be made in the TABLE constructor. I'm creating some other objects that have CABLEs in them, but I'm pretty sure none of them are getting destroyed. I've got one implicit cast where I grab a line from cout and pass that into a function that's looking for a CABLE, so the VS is just doing that on its own. Don't know where the problem might be coming from. ________________________________________________________________________ The question "Do computers think?" is the same as "Can submarines swim?" Signature Red Studios Jeryth
-
Yeah, saw the destructor reference and that was the first thing I checked before I posted. If only it would have been so easy. I'm not explicitly calling for any CABLEs to be made in the TABLE constructor. I'm creating some other objects that have CABLEs in them, but I'm pretty sure none of them are getting destroyed. I've got one implicit cast where I grab a line from cout and pass that into a function that's looking for a CABLE, so the VS is just doing that on its own. Don't know where the problem might be coming from. ________________________________________________________________________ The question "Do computers think?" is the same as "Can submarines swim?" Signature Red Studios Jeryth
Of course I didn't mean to imply that you would make such an elementary error :-D, but there's no question (at least in my mind :)) that the linker can't find the implementation of CABLE::~CABLE, so something's gotta be wrong. You could try to put {} after the declaration in header file to make ~CABLE inline, that way you're sure it's defined:
class CABLE { public: virtual ~CABLE() {}; }
If that gets rid of the linker error then recheck the definition of ~CABLE in your code. Regarding calling of the constructor, it's called when temporary CABLE objects are constructed and destructed, for example during an assignment. Furthermore, the second linker error indicates that the destructor is called from a structured exception handler (the "_unwindfunclet" part sounds like stack unwinding to me) Perhaps you could post some code to show the declaration and implemenations, or is it too large chunks? cheers Steen (from my home computer) -
Of course I didn't mean to imply that you would make such an elementary error :-D, but there's no question (at least in my mind :)) that the linker can't find the implementation of CABLE::~CABLE, so something's gotta be wrong. You could try to put {} after the declaration in header file to make ~CABLE inline, that way you're sure it's defined:
class CABLE { public: virtual ~CABLE() {}; }
If that gets rid of the linker error then recheck the definition of ~CABLE in your code. Regarding calling of the constructor, it's called when temporary CABLE objects are constructed and destructed, for example during an assignment. Furthermore, the second linker error indicates that the destructor is called from a structured exception handler (the "_unwindfunclet" part sounds like stack unwinding to me) Perhaps you could post some code to show the declaration and implemenations, or is it too large chunks? cheers Steen (from my home computer)No, no, I've been known to make basic mistakes. Nearly tore all my hair out after typing 50 pages of code and couldn't get it to compile. Then found a missing semicolon about 20 lines up from where the compiler had flagged the error. No, found out the problem. I had CABLE files in a different directory ( I wanted to keep them in a generic use folder ) and had added that directory to the project include folders, but had not added the files themselves to the project. Now compiling and linking is fine, but I've got yet ANOTHER problem. I run the program in the debugger and after I get through a few menus, I get this: DAMAGE: before Normal block ( #92 ) at ( 0x00323798 ) In stepping back through the debugger, it hilights the CABLE destructor. In particular, the line
delete [] cable;
Thecable
var is a char * array so I don't know why it wouldn't be able to delete it. Any ideas here? ________________________________________________________________________ The question "Do computers think?" is the same as "Can submarines swim?" Signature Red Studios Jeryth -
No, no, I've been known to make basic mistakes. Nearly tore all my hair out after typing 50 pages of code and couldn't get it to compile. Then found a missing semicolon about 20 lines up from where the compiler had flagged the error. No, found out the problem. I had CABLE files in a different directory ( I wanted to keep them in a generic use folder ) and had added that directory to the project include folders, but had not added the files themselves to the project. Now compiling and linking is fine, but I've got yet ANOTHER problem. I run the program in the debugger and after I get through a few menus, I get this: DAMAGE: before Normal block ( #92 ) at ( 0x00323798 ) In stepping back through the debugger, it hilights the CABLE destructor. In particular, the line
delete [] cable;
Thecable
var is a char * array so I don't know why it wouldn't be able to delete it. Any ideas here? ________________________________________________________________________ The question "Do computers think?" is the same as "Can submarines swim?" Signature Red Studios JerythI think you made a memory overwrite somewhere in your code. MFC
new
puts guard bytes around your allocated block and checks if something has screwed up your block everytime you call new or delete - that's why you get the message in the destructor, as that's probably the first time after the error occurred that new or delete gets called. Alas, it has nothing to do with the destructor or the delete[] call as such. See this[^] MSDN article for more info. Recheck your code for places where you use strcpy or similar function without checking the length of the arguments, especially your cable variable. Use strncpy instead. Cheers Steen -
I think you made a memory overwrite somewhere in your code. MFC
new
puts guard bytes around your allocated block and checks if something has screwed up your block everytime you call new or delete - that's why you get the message in the destructor, as that's probably the first time after the error occurred that new or delete gets called. Alas, it has nothing to do with the destructor or the delete[] call as such. See this[^] MSDN article for more info. Recheck your code for places where you use strcpy or similar function without checking the length of the arguments, especially your cable variable. Use strncpy instead. Cheers SteenHmm, I didn't make this an MFC project per se, just started with an empty solution but I guess some MFC is still being put it automatically. That link was rather helpful, shows the same error message I'm getting so that should be the right track. I'm not using
strcpy
orstrncpy
anywhere. I use my own loops to copy element by element in CABLE. In fact the onlystring
function I think I'm using isstrlen
. Here's the CABLE class in it's entirty. It's pretty simplistic, I'm pretty much just doing it for practice with plans to add on to it as I learn more.#include CABLE::CABLE()
{
cable = new char[1];
cable[0] = '\0';
length = 0;
}//Private constructor, used only to create a temp CABLE of set size that is NULL filled.
CABLE::CABLE( int newLength )
{
cable = new char[newLength+1];
length = newLength;
for( int i = 0; i <= length; ++i )
{
cable[i] = '\0';
}
}CABLE::CABLE( const char * const newCable )
{
length = strlen( newCable );
cable = new char [length+1];
for( int i = 0; i <= length; ++i )
{
cable[i] = newCable[i];
}
cable[length] = '\0';
}CABLE::CABLE( const CABLE & rhs )
{
length = rhs.GetLength();
cable = new char[length+1];
for( int i = 0; i <= length; ++i )
{
cable[i] = rhs[i];
}
cable[length] = '\0';
}CABLE::~CABLE()
{
delete cable;
cable = NULL;
length = 0;
}CABLE & CABLE::operator=( const CABLE & rhs )
{
if ( this != &rhs )
{
delete [] cable;
length = rhs.GetLength();
cable = new char[length+1];
for( int i = 0; i <= length; ++i )
{
cable[i] = rhs[i];
}
cable[length] = '\0';
}return \*this;
}
char & CABLE::operator[]( int offset )
{
if ( offset > length )
{
return cable[length-1];
}
else
{
return cable[offset];
}
}char CABLE::operator[]( int offset ) const
{
if ( offset > length )
{
return cable[length-1];
}
else
{
return cable[offset];
}
}CABLE CABLE::operator+( const CABLE & rhs )
{
int totalLength = length + rhs.GetLength();
CABLE temp( totalLength );
for( int i = 0; i < length; ++i )
{
temp[i] = cable[i];
}
for( int j = 0; j < rhs.GetLength(); ++j, ++i )
{
temp[i] = rhs[j];
}
temp[totalLength] = '\0';return temp;
}
void CABLE::operator+=( const CABLE & rhs )
{
int totalLength = length + rhs.GetLength();
CABLE temp( totalLength );
for( int i = 0; i < length; ++i )
{
temp[i] = cable[i];
}
for( int j = 0; -
Hmm, I didn't make this an MFC project per se, just started with an empty solution but I guess some MFC is still being put it automatically. That link was rather helpful, shows the same error message I'm getting so that should be the right track. I'm not using
strcpy
orstrncpy
anywhere. I use my own loops to copy element by element in CABLE. In fact the onlystring
function I think I'm using isstrlen
. Here's the CABLE class in it's entirty. It's pretty simplistic, I'm pretty much just doing it for practice with plans to add on to it as I learn more.#include CABLE::CABLE()
{
cable = new char[1];
cable[0] = '\0';
length = 0;
}//Private constructor, used only to create a temp CABLE of set size that is NULL filled.
CABLE::CABLE( int newLength )
{
cable = new char[newLength+1];
length = newLength;
for( int i = 0; i <= length; ++i )
{
cable[i] = '\0';
}
}CABLE::CABLE( const char * const newCable )
{
length = strlen( newCable );
cable = new char [length+1];
for( int i = 0; i <= length; ++i )
{
cable[i] = newCable[i];
}
cable[length] = '\0';
}CABLE::CABLE( const CABLE & rhs )
{
length = rhs.GetLength();
cable = new char[length+1];
for( int i = 0; i <= length; ++i )
{
cable[i] = rhs[i];
}
cable[length] = '\0';
}CABLE::~CABLE()
{
delete cable;
cable = NULL;
length = 0;
}CABLE & CABLE::operator=( const CABLE & rhs )
{
if ( this != &rhs )
{
delete [] cable;
length = rhs.GetLength();
cable = new char[length+1];
for( int i = 0; i <= length; ++i )
{
cable[i] = rhs[i];
}
cable[length] = '\0';
}return \*this;
}
char & CABLE::operator[]( int offset )
{
if ( offset > length )
{
return cable[length-1];
}
else
{
return cable[offset];
}
}char CABLE::operator[]( int offset ) const
{
if ( offset > length )
{
return cable[length-1];
}
else
{
return cable[offset];
}
}CABLE CABLE::operator+( const CABLE & rhs )
{
int totalLength = length + rhs.GetLength();
CABLE temp( totalLength );
for( int i = 0; i < length; ++i )
{
temp[i] = cable[i];
}
for( int j = 0; j < rhs.GetLength(); ++j, ++i )
{
temp[i] = rhs[j];
}
temp[totalLength] = '\0';return temp;
}
void CABLE::operator+=( const CABLE & rhs )
{
int totalLength = length + rhs.GetLength();
CABLE temp( totalLength );
for( int i = 0; i < length; ++i )
{
temp[i] = cable[i];
}
for( int j = 0;If it's not an MFC App Wizard generated project you shouldn't have any MFC. The only thing I can see in your code is that you use delete cable instead of delete[] cable in the destructor, but from your previous post I guess that's a typo (you said earlier that the debugger highlighted
delete[] cable
in the destructor). How is CABLE used in your code? Which methods are called? That may give some clues. Cheers Steen