Server Help Forum Index Server Help
Community forums for Subgame, ASSS, and bots
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   StatisticsStatistics   RegisterRegister 
 ProfileProfile   Login to check your private messagesLogin to check your private messages   LoginLogin (SSL) 

Server Help | ASSS Wiki (0) | Shanky.com
C++ : Inheritance,Template and Threads problems

 
Post new topic   Reply to topic Printable version
 View previous topic  C coding challenge Post :: Post [C++] Stupid bug... [SOLVED]  View next topic  
Author Message
Samapico
No, these DO NOT look like penises, ok?


Joined: May 08 2003
Posts: 1252
Offline

PostPosted: Mon Sep 28, 2009 1:28 am    Post subject: C++ : Inheritance,Template and Threads problems Reply to topic Reply with quote

I have a class (Layer) from which another class (Layer_net) inherits. Other classes will inherit from it eventually.
I made the Layer class a template because there is a specific data type that I want to specify for each child class.
I'm having problems to define class functions outside the class body. They compile fine, but the linker freaks out when one of the function appears in the code.

Code: Show/Hide
#define T_LAYER template <typename T>

T_LAYER
class Layer
{
public:
//stuff...
void Func1();
void Func2() { printf("hi, this is Func2\n"); }
};

T_LAYER
void Layer<T>::Func1()
{
   printf("hi, this is Func1\n");
}




//meanwhile, in another class not far away...

struct HeaderNetwork
{
   char ip[4];
};

class Layer_net : public Layer<HeaderNetwork>
{
public:
   //stuff
};



//and in the main...

int main(void)
{
   Layer_net net;

   net.Func1();
   net.Func2();
}

Ok, it seems the above code works if you put it all in the same file.

I then split it up in a header file and 2 cpp's like so:

header.h
Code: Show/Hide

#include <stdio.h>
#include <stdlib.h>

struct HeaderNetwork
{
   char ip[4];
};


template <typename T>
class Layer
{
public:

   //stuff...
   void Func1(int);
   void Func2() { printf("hi, this is Func2\n"); }
};



//meanwhile, in another class not far away...

class Layer_net : public Layer<HeaderNetwork>
{
public:
   //stuff
};



layer.cpp
Code: Show/Hide

#include <stdio.h>
#include <stdlib.h>


#include "header.h"

template <typename T>
void Layer<T>::Func1(int a)
{
   printf("hi, this is Func1\n");
}


main.cpp
Code: Show/Hide

#include "header.h"

//and in the main...

int main(void)
{
   Layer_net net;

   net.Func1(1);
   net.Func2();

   getchar();
}


Build results:
1>------ Build started: Project: test, Configuration: Debug Win32 ------
1>Compiling...
1>main.cpp
1>Generating Code...
1>Compiling...
1>layer.cpp
1>Generating Code...
1>Linking...
1>main.obj : error LNK2019: unresolved external symbol "public: void __thiscall Layer<struct HeaderNetwork>::Func1(int)" (?Func1@?$Layer@UHeaderNetwork@@@@QAEXH@Z) referenced in function _main
1>D:\Sam\Prog Projects\GPA785\trunk\Debug\test.exe : fatal error LNK1120: 1 unresolved externals
1>Build log was saved at "file://d:\Sam\Prog Projects\GPA785\trunk\test\Debug\BuildLog.htm"
1>test - 2 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========


Can anyone figure out what's happening?
Using Visual Studio 2005
_________________
(Insert a bunch of dead links here)


Last edited by Samapico on Mon Sep 28, 2009 2:22 am, edited 1 time in total
Back to top
View users profile Send private message Add User to Ignore List
Samapico
No, these DO NOT look like penises, ok?


Joined: May 08 2003
Posts: 1252
Offline

PostPosted: Mon Sep 28, 2009 2:00 am    Post subject: Reply to topic Reply with quote

I think I found my answer

http://cpp.developpez.com/faq/cpp/?page=templates#DIVERS_templates
(in french)

Basically, for some reason I have to make the layer.cpp NOT compile, and instead of including the header in it, I must include the cpp at the end of the header file...


I don't really understand why, but it works tongue.gif
Back to top
View users profile Send private message Add User to Ignore List
Samapico
No, these DO NOT look like penises, ok?


Joined: May 08 2003
Posts: 1252
Offline

PostPosted: Mon Sep 28, 2009 2:21 am    Post subject: Reply to topic Reply with quote

I have another somewhat related problem, and I'm pretty tired now, so excuse me if it's dumb:


Still in my template class, I got some function declared:

DWORD WINAPI threadloop(LPVOID iValue);

and defined later.
And then I want to create a thread in there...

First try:
Code: Show/Hide
hthread = CreateThread(NULL, 0, threadloop, "", 0, &threadID);   
error C3867: 'Layer<T>::threadloop': function call missing argument list; use '&Layer<T>::threadloop' to create a pointer to member

Ok... second try:
Code: Show/Hide
hthread = CreateThread(NULL, 0, &Layer<T>::threadloop, "", 0, &threadID);   
error C2664: 'CreateThread' : cannot convert parameter 3 from 'DWORD (__stdcall Layer<T>::* )(LPVOID)' to 'LPTHREAD_START_ROUTINE'

And then I desperately tried to typecast it:
Code: Show/Hide
hthread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(&Layer<T>::threadloop), "", 0, &threadID);


It failed.
A lot of stuff in there looks weird to me, but I started from an example given by the teacher... but yeah, he wasn't using templates, obviously tongue.gif
Back to top
View users profile Send private message Add User to Ignore List
Doc Flabby
Server Help Squatter


Joined: Feb 26 2006
Posts: 636
Offline

PostPosted: Mon Sep 28, 2009 5:05 am    Post subject: Reply to topic Reply with quote

I recommend looking at pthreads icon_smile.gif or using a C++ framework. Working directly with the Windows API is a PITA but anyways:

Code: Show/Hide

hthread = CreateThread(NULL, 0, &Layer<T>::threadloop, "", 0, &threadID);


The problem here is the compiler does not know what T is. Creating an instance of the class Layer<T> and pass it to the function might fix this problem.

eg,
Code: Show/Hide

Layer<int> t = new Layer<int>;
hthread = CreateThread(NULL, 0, &t::threadloop, "", 0, &threadID);


This might not work btw tongue.gif

I'm not overally familier with templates (i've not used them) in C++ but this link might help http://docs.google.com/gview?a=v&q=cache:twJe98TSVCIJ:www.allankelly.net/static/writing/overload/Threads/ThreadTemplate.pdf+templates+theading&hl=en&gl=uk&sig=AFQjCNEN1kd0XAxuQ2BA4Gq6xtyPrEfVsA[/code]
_________________
Rediscover online gaming. Get Subspace | STF The future...prehaps
Back to top
View users profile Send private message Add User to Ignore List
Samapico
No, these DO NOT look like penises, ok?


Joined: May 08 2003
Posts: 1252
Offline

PostPosted: Mon Sep 28, 2009 10:21 am    Post subject: Reply to topic Reply with quote

hmmm, the CreateThread call is from the Layer class itself as well, so it should know what T is icon_surprised.gif

Code: Show/Hide
T_LAYER
void Layer<T>::Start(void)
{
   if (hthread == NULL)
   {
      run_thread = true;
      hthread = CreateThread(NULL, 0, threadloop, "", 0, &threadID);   
   }
}


Your suggestion doesn't work, I also tried with this->
Back to top
View users profile Send private message Add User to Ignore List
Doc Flabby
Server Help Squatter


Joined: Feb 26 2006
Posts: 636
Offline

PostPosted: Mon Sep 28, 2009 10:44 am    Post subject: Reply to topic Reply with quote

You would think it would, but it is C++ after all tongue.gif

I found the source for that link which has threads created inside Templates (go to bottom of the page)

http://www.allankelly.net/writing/softdesign.html
http://www.allankelly.net/static/writing/overload/Threads/threadssource.zip

From the source (snippit) you can see its a bit of a hack job tongue.gif Essentially you have to pass the RunThread an object that implements a "run" function (this might sound familier tongue.gif)
Code: Show/Hide

   void RunThread(   T      &x,
               long   stackSize = 0)
   {
      // each object represents one thread
      // therefore, should not launch multiple threads with one object
      assert (NULL == m_threadHandle);

      // other parameters may be dafaulted if needed
      DWORD dwStack = (DWORD) stackSize;

      // create a  thread
      m_threadHandle = CreateThread( 
                        NULL,         // pointer to thread security attributes 
                        dwStack,      // initial thread stack size, in bytes
                        StartRun,      // pointer to thread function 
                        &x,            // argument for new thread
                        0,            // creation flags
                        &m_threadId);   // pointer to returned thread identifier
      DWORD last = GetLastError();   // useful for debug stepping

      if (NULL == m_threadHandle)
      {
         throw std::runtime_error("Failed to start thread");
      }
   }

static unsigned long __stdcall StartRun(void *param)
   {   
      T* object = static_cast<T*> (param);   // reclaim object type
      object->Run();
      return 0;
   }
Back to top
View users profile Send private message Add User to Ignore List
Samapico
No, these DO NOT look like penises, ok?


Joined: May 08 2003
Posts: 1252
Offline

PostPosted: Mon Sep 28, 2009 7:10 pm    Post subject: Reply to topic Reply with quote

hmmmm, but the argument of RunThread would still have to be of type Layer<T>, since I want the Run() function to be in there

Not sure how to translate this in my project...
Back to top
View users profile Send private message Add User to Ignore List
Dr Brain
Flip-flopping like a wind surfer


Age:38
Gender:Gender:Male
Joined: Dec 01 2002
Posts: 3502
Location: Hyperspace
Offline

PostPosted: Mon Sep 28, 2009 7:32 pm    Post subject: Reply to topic Reply with quote

This is why C++ always seems horrible to me. Simple, easy things are complicated and non-intuitive. You use it if you have to, but stay away from it otherwise.
_________________
Hyperspace Owner

Smong> so long as 99% deaths feel lame it will always be hyperspace to me
Back to top
View users profile Send private message Add User to Ignore List AIM Address Yahoo Messenger MSN Messenger
Samapico
No, these DO NOT look like penises, ok?


Joined: May 08 2003
Posts: 1252
Offline

PostPosted: Mon Sep 28, 2009 10:54 pm    Post subject: Reply to topic Reply with quote

I could go the easy way and get rid of the template, that would just give me some copy paste to do
Back to top
View users profile Send private message Add User to Ignore List
Samapico
No, these DO NOT look like penises, ok?


Joined: May 08 2003
Posts: 1252
Offline

PostPosted: Thu Oct 01, 2009 11:57 am    Post subject: Reply to topic Reply with quote

Samapico wrote:
I could go the easy way and get rid of the template, that would just give me some copy paste to do
Oh well... I went the easy way tongue.gif
I didn't actually need the members of the type in the base class, I only needed to know the sizeof it to allocate memory and such. So I just used an int for the size, and initialize it to sizeof(MyHeader) in the derived class.

F*** templates.
Back to top
View users profile Send private message Add User to Ignore List
Display posts from previous:   
Post new topic   Reply to topic    Server Help Forum Index -> Non-Subspace Related Coding All times are GMT - 5 Hours
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You can attach files in this forum
You can download files in this forum
View online users | View Statistics | View Ignored List


Software by php BB © php BB Group
Server Load: 440 page(s) served in previous 5 minutes.

phpBB Created this page in 0.583498 seconds : 36 queries executed (80.6%): GZIP compression disabled