Sign in to follow this  
iliak

Prototype, implementation & linker error

Recommended Posts

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 ?

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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...

Share this post


Link to post
Share on other sites
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) ?

Share this post


Link to post
Share on other sites
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...

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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).

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
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.

Share this post


Link to post
Share on other sites
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.

Although virtual and the __forceinline keyword of certain M$ compilers might indeed be disallowed. Remember: inline is only a recommendation, not a demand.

Share this post


Link to post
Share on other sites
Quote:
Original post by MaulingMonkey
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.

Although virtual and the __forceinline keyword of certain M$ compilers might indeed be disallowed. Remember: inline is only a recommendation, not a demand.

Even with Microsoft's __forceinline it is defined to only force inline in places where it's possible, otherwise the call is made normally. They actually even make reference to virtual functions in their description for __forceinline.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this