Prototype, implementation & linker error

Started by
10 comments, last by Polymorphic OOP 19 years, 6 months ago
Hi, here's my source cGuiElement.h

#ifndef	CGUIELEMENT_H
#define	CGUIELEMENT_H
	
class cGuiElement
{
public:
	virtual	bool	Init(void)
		{return true;};
	virtual	void	Render(void)
		{};					
};
#endif

cGuiImage

#ifndef	CGUIIMAGE_H
#define	CGUIIMAGE_H

#include "cGuiElement.h"

class cGuiImage : public cGuiElement
{
public:

	bool	Init(char *file)
	{
		return true;
	};

};
#endif

everything compile & link well. But if I try to move the implementation to a .cpp, i got a linker error. What can i do ?
- Iliak -
[ ArcEngine: An open source .Net gaming framework ]
[ Dungeon Eye: An open source remake of Eye of the Beholder II ]
Advertisement
First thing, watch out, you changed the signature of Init in cGuiImage, so it's not overriding the version in cGuiElement.

Secondly, rembember to make cGuiElement's destructor private virtual.

Thirdly, post some more code, this will not even compile (no main() function).

Finally - what is the linker error?

[Edited by - Fruny on October 3, 2004 6:25:45 PM]
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
I found *a* solution and now my project can run, but i'm not pleased with it... Here are the sources :

cGuiElement.h
class cGuiElement{public:	virtual	bool	Init(void)	{return true;};	virtual	void	Render(void)	{};}




cGuiImage.h
#include "cGuiElement.h"class cGuiImage : public cGuiElement{public:	bool	Init(char *file)	{		return true;	};};



Like that my source will compile, link and run perfectly. But if i make changes like below :


cGuiImage.h
#include "cGuiElement.h"class cGuiImage : public cGuiElement{public:	bool	Init(char *file);};


cGuiImage.cpp
bool cGuiImage::Init(char *file){	return true;}


I'm getting a linker error.

The thing i dont understand is why when i move the code implementation from the .h to the .cpp i got this linker error :

(sorry it's in french)
RnR.obj : error LNK2019: symbole externe non résolu "public: bool __thiscall cGuiImage::Init(char *)" (?Init@cGuiImage@@QAE_NPAD@Z) référencé dans la fonction _main
RnR.exe : fatal error LNK1120: 1 externes non résolus
- Iliak -
[ ArcEngine: An open source .Net gaming framework ]
[ Dungeon Eye: An open source remake of Eye of the Beholder II ]
I'm not sure what's causing your problems, but there are two things I noticed about your code that look wrong. I'm not certain whether they're really wrong or not, but anyway...

Firstly: function definitions don't have semicolons after them.

For example:

class cGuiImage : public cGuiElement{public:  bool Init(char *file)  {    return true;  }; //this semicolon should not be here.};


Semis are only for declarations, so they come after prototypes and class declarations.

The other thing is that I'm fairly sure you're not allowed to make virtual functions inline, and I'm surprised your compiler is letting you get away with it. The two properties are contradictory.

Like I said, I don't know whether changing those would help. It's all I can think of, though.
-------------"On two occasions, I have been asked [by members of Parliament], 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?' I am not able to rightly apprehend the kind of confusion of ideas that could provoke such a question."- Charles Babbage (1791-1871)
First, some more infos. The source code is from a dll and the linker error is in the .exe that use this dll.

Fruny:
I tried your remarks and nothing changed. The thing i don't understand why is when I move the code from the .h to the .cpp I get a linker error.
I tried to make a new project and paste all my files in this new project, and nothing changed...
- Iliak -
[ ArcEngine: An open source .Net gaming framework ]
[ Dungeon Eye: An open source remake of Eye of the Beholder II ]
Quote:Original post by iliak
First, some more infos. The source code is from a dll and the linker error is in the .exe that use this dll.


Quote:RnR.obj : error LNK2019: symbole externe non résolu "public: bool __thiscall cGuiImage::Init(char *)" (?Init@cGuiImage@@QAE_NPAD@Z) référencé dans la fonction _main


Are the symbols properly exported (made visible to code that uses the DLL) ?
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Quote:Original post by Fruny
Secondly, rembember to make cGuiElement's destructor private.
Private? I assume you mean virtual...

You can't do it like that, since as Fruny said, the symbols aren't exported. You could try making the function pure virtual, which would probably be a good idea here anyway since you'll never create a cGuiElement, only a derived type. Actually, looking over your code again, I'm not sure that pure virtual would help...
Quote:Original post by Evil Steve
Quote:Original post by Fruny
Secondly, rembember to make cGuiElement's destructor private.
Private? I assume you mean virtual...


Yes. That was a braino.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Quote:Original post by SoulSkorpion
The other thing is that I'm fairly sure you're not allowed to make virtual functions inline, and I'm surprised your compiler is letting you get away with it. The two properties are contradictory.

They are not contradictory. You're probably thinking this because you are assuming that all calls to a function declared to be virtual are dynamically bound. This is not the case. Take, for instance, when you are interfacing directly with an object not via a pointer or reference. In these cases, it is impossible to be refering to any type other than the type used in the object's declaration. Therefore, the function can be called just like it were a non-virtual function making it just as fast as a regular function call and very easy to be inlined.

Quote:Original post by Evil Steve
You could try making the function pure virtual, which would probably be a good idea here anyway since you'll never create a cGuiElement, only a derived type.

Yeah. Right now, with the code provided, it looks as though your cGuiElement should be an abstract base class with all pure virtual functions. It seems like it would never make sense to create a cGuiElement and the default virtual function implementations seem arbitrary. You may be better off making them pure virtual functions, and if you really wanted, also provide those semi-blank implementations for the functions as well.

Quote:Original post by Fruny
Secondly, rembember to make cGuiElement's destructor virtual

While I normally would agree, I'm not entirely sure that's necessary here. He never says he has to delete the object through a pointer to the base so I wouldn't make the assumption that it's something he wants. It may just be better to make the destructor protected (or leave it public if he really wantes to keep his cGuiElement as a concrete class, which I wouldn't recommend).




Finally, to the original poster, I do not recommend declaring your class and having only the function implementations in a DLL as you are describing unless you are absolutely positive that is what you want (you may actually just want a static-link library). The reason why I don't recommend it is because one of the primary reasons for using a DLL is that the implementation of objects in the DLL can be changed without affecting client executables. The problem is, since you are only putting the member function implementations in the DLL and are leaving the structure of the type accessable from clients, you are limiting your DLL implementation to the way you originally defined your class. This makes it impossible to update your object's structure -- you can only change the function definitions.

Instead, you would probably be better off making your child classes based off of intermediate classes with all pure virtual functions and have the actual objects allocated in the DLL and manipulated from the client. This way, the implementation of the Gui element can change when the DLL is modified.

If you don't do that and aren't concerned with updating the implementation separate from your client executables, you may just want to use a static link library instead of a DLL (which will also very likely speed up performance as well).
Quote:Original post by Polymorphic OOP
Quote:Original post by SoulSkorpion
The other thing is that I'm fairly sure you're not allowed to make virtual functions inline, and I'm surprised your compiler is letting you get away with it. The two properties are contradictory.

They are not contradictory. You're probably thinking this because you are assuming that all calls to a function declared to be virtual are dynamically bound. This is not the case. Take, for instance, when you are interfacing directly with an object not via a pointer or reference. In these cases, it is impossible to be refering to any type other than the type used in the object's declaration. Therefore, the function can be called just like it were a non-virtual function making it just as fast as a regular function call and very easy to be inlined.

Ah, right. Forgot about that virtual only kicks in if you use pointers\references.

This topic is closed to new replies.

Advertisement