Recommended Posts

iliak    278
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 on other sites
Fruny    1658
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 on other sites
iliak    278
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;}

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 on other sites
SoulSkorpion    238
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 on other sites
iliak    278
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 on other sites
Fruny    1658
Quote:
 Original post by iliakFirst, 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 on other sites
Evil Steve    2017
Quote:
 Original post by FrunySecondly, 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 on other sites
Fruny    1658
Quote:
Original post by Evil Steve
Quote:
 Original post by FrunySecondly, rembember to make cGuiElement's destructor private.
Private? I assume you mean virtual...

Yes. That was a braino.

Share on other sites
Quote:
 Original post by SoulSkorpionThe 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 SteveYou 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 FrunySecondly, 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 on other sites
Guest Anonymous Poster
Quote:
Original post by Polymorphic OOP
Quote:
 Original post by SoulSkorpionThe 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 on other sites
MaulingMonkey    1728
Quote:
Original post by Polymorphic OOP
Quote:
 Original post by SoulSkorpionThe 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.

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 SoulSkorpionThe 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.