Link to home
Start Free TrialLog in
Avatar of ktd85
ktd85

asked on

can't call member function of a class-object returned by a function

Getting the following compile-error:
g++ -c -Wall -pthread -I/usr/include/gnet-2.0 -I/usr/lib/gnet-2.0/include/ -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include  -pthread -lgnet-2.0 -lgthread-2.0 -lrt -lglib-2.0 main.cpp -o main.o
main.cpp: In function »int main()«:
main.cpp:9: Fehler: »gruetze.UDPServer::getClientManager« hat keinen Klassentyp
make: *** [main.o] Fehler 1
//ClientManager Class
class ClientManager{
private:
vector<Client> clients;
 
public:
  ClientManager(void);
  bool registerClient(Client test);
  int getCount(void);
  ~ClientManager(void);
};
 
//Class udpserver
class UDPServer{
 
private:
  int lport;
  GUdpSocket* server;
  gint ttl;
  gint rv;
  GInetAddr* addr;
  gchar buffer[1024];
  pthread_t serverthread;
  ClientManager cm;
  void* thread();
  static void* _run(void* This)
  {
    return ((UDPServer*)This)->thread();
  };
 
public:
  UDPServer(int port);
  ClientManager getClientManager();
  ~UDPServer();
};
 
//function-code:
ClientManager UDPServer::getClientManager()
{
return this->cm;
}
 
//Called function:
int ClientManager::getCount(void)
{
return clients.size();
}
 
 
//Line containing the error:
printf("%s",gruetze.getClientManager.getCount());

Open in new window

Avatar of Infinity08
Infinity08
Flag of Belgium image

Could you post the complete code ? At least the part where the error occurs (line 9 in main.cpp, as well as the declarations for all variables used, etc.).
Avatar of ktd85
ktd85

ASKER


//main.cpp
#include "udpserver.h"
#include "serial.h"
 
int main()
{
UDPServer gruetze(1337);
while (true)
{
gruetze.getClientManager();
sleep(100);
}
}
 
//udpserver.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <glib.h>
#include <unistd.h>
#include <string>
#include "clientmanager.h"
#include <gnet.h>
#include <udp.h>
#include <pthread.h>
 
class UDPServer{
 
private:
  int lport;
  GUdpSocket* server;
  gint ttl;
  gint rv;
  GInetAddr* addr;
  gchar buffer[1024];
  pthread_t serverthread;
  ClientManager cm;
  void* thread();
  static void* _run(void* This)
  {
    return ((UDPServer*)This)->thread();
  };
 
public:
  UDPServer(int port);
  ClientManager getClientManager();
  ~UDPServer();
};
 
 
//udpserver.c
#include "udpserver.h"
using namespace std;
 
 
 
UDPServer::UDPServer(int port)
{
  this->lport=port;
  gnet_init ();
  this->server=gnet_udp_socket_new_with_port(port);
  if (this->server == NULL)
    {
      fprintf (stderr, "Could not create server on port %d\n", port);
      exit (EXIT_FAILURE);
    }
  pthread_create( &serverthread, NULL, _run, this);
}
 
ClientManager UDPServer::getClientManager()
{
cm.getCount();
return NULL;
//return this->cm;
}
 
void* UDPServer::thread()
{
while (true)
  {
     gint bytes_received;
     std::string b;
     bytes_received = gnet_udp_socket_receive (this->server, this->buffer, sizeof(this->buffer),&this->addr);
     b=this->buffer;
     b.erase(bytes_received);
     if (b.find("ch bin da"))
     {
       Client m;
       cm.registerClient(m);
     }
     printf("%s",b.c_str());
  }
}
 
UDPServer::~UDPServer() {
  pthread_join( serverthread, NULL );
}

Open in new window

I assume that gruetze is an object of type UDPServer ?

Then, if you want to call the getClientManager method on it, you need to do :

        gruetze.getClientManager()

instead of :

>>    gruetze.getClientManager

Note that the getClientManager method returns a copy of the ClientManager object ... Maybe it should be returned by reference, or by pointer ?

Furthermore, you continue by calling the getCount method on the ClientManager object, but that method returns an int, not the char* that your printf expects (%s).
btw, the code you posted is not the same code you posted earlier - it doesn't contain the printf ...
Avatar of ktd85

ASKER

oh, sorry. i modified...
So, does that solve your problem ? If not, can you post the new code, as well as the new error message you get ?
Avatar of ktd85

ASKER

Corrected the ()-thing.
Is there a method to return the referenc to the original object?
Do have to change the function-call?
Avatar of ktd85

ASKER

addition to my last post. After i corrected the ()-thing the code worked!
Is there a method to return the referenc to the original object?
Do have to change the function-call?
>> addition to my last post. After i corrected the ()-thing the code worked!

Did you also fix the int vs. %s thing ? By using %d instead of %s for example.


>> Is there a method to return the referenc to the original object?
>> Do have to change the function-call?

It depends what you're trying to do. But you could return a reference to the object instead of a copy to the object, yes. That would indeed involve modifying the method.
Type obj;
 
Type fun_copy() {           // <--- return a copy of the object
  return obj;
}
 
Type &fun_ref() {           // <--- return a reference to the object
  return obj;
}
 
 
// and the calling code :
 
Type obj2 = fun_copy();
obj2.some_method();         // <--- will be called on the copy, not the original object
 
Type &obj_ref = fun_ref();
obj_ref.some_method();      // <--- will be called on the original object (obj)

Open in new window

Avatar of ktd85

ASKER

Yes, i corrected the %d-thing too.

Is there a possibility to make the call in one line?
Type &obj_ref = fun_ref();
obj_ref.some_method();  
>> Is there a possibility to make the call in one line?

Sure :

        fun_ref().some_method();

will call the some_method method on the original object (obj).
Avatar of ktd85

ASKER

I included a message in the constructor and destructor.
After starting the program i'm now receiving masses of the following message:
Client destroyed.
Client destroyed.
Client destroyed.
Client destroyed.
Client destroyed.

Is the refereced object destroyed after the method call?
//client.cpp
#include "client.h"
using namespace std;
 
Client::Client(void)
{
  fprintf (stdout, "Client created.\r\n");
}
 
Client::~Client(void) {
 fprintf (stdout, "Client destroyed.\r\n");
}
 
//changed method:
ClientManager &UDPServer::getClientManager()
{
return this->cm;
}
 
//main.cpp:
int main()
{
UDPServer gruetze(1337);
while (true)
{
printf("Anzahl der Clients: %d /r/n",gruetze.getClientManager().getCount());
sleep(2);
}
}

Open in new window

>> Client destroyed.

You'll receive one such message each time a Client object is destroyed.

The UDPServer::thread() code you posted earlier has an infinite loop that potentially creates and destroys a Client object for each iteration. That's probably the reason ...
Avatar of ktd85

ASKER

Hi,

i think the thread which is started in the udpserver-class does not cause this thing.
I commented out the following line of my main-loop and it stopped producing the messages:
printf("Anzahl der Clients: %d /r/n",gruetze.getClientManager().getCount());

any idea?
Nothing in the code you posted earlier suggests the creation of Client objects, except for the ones in the thread method.

Maybe you could post the complete, current code ?
Avatar of ktd85

ASKER

yes
//main.cpp
#include "udpserver.h"
#include "serial.h"
 
int main()
{
UDPServer gruetze(1337);
while (true)
{
//printf("Anzahl der Clients: %d /r/n",gruetze.getClientManager().getCount());
sleep(2);
}
}
 
 
//client.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
 
class Client{
public:
  Client(void);
  ~Client(void);
};
 
 
//client.cpp
#include "client.h"
using namespace std;
Client::Client(void)
{
  fprintf (stdout, "Client created.\r\n");
}
Client::~Client(void) {
 fprintf (stdout, "Client destroyed.\r\n");
}
 
//clientmanager.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <vector>
#include "client.h"
using namespace std;
class ClientManager{
private:
vector<Client> clients;
public:
  ClientManager(void);
  bool registerClient(Client test);
  int getCount(void);
  ~ClientManager(void);
};
 
//clientmanager.cpp
#include "clientmanager.h"
using namespace std;
ClientManager::ClientManager(void)
{
  fprintf (stdout, "Client Manager Class created.");
}
bool ClientManager::registerClient(Client test)
{
clients.push_back(test);
return true;
}
int ClientManager::getCount(void)
{
return clients.size();
}
ClientManager::~ClientManager(void) {
 fprintf (stdout, "Client Manager Class destroyed.");
}
 
//udpserver.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <glib.h>
#include <unistd.h>
#include <string>
#include "clientmanager.h"
#include <gnet.h>
#include <udp.h>
#include <pthread.h>
 
class UDPServer{
 
private:
  int lport;
  GUdpSocket* server;
  gint ttl;
  gint rv;
  GInetAddr* addr;
  gchar buffer[1024];
  pthread_t serverthread;
  ClientManager cm;
  void* thread();
  static void* _run(void* This)
  {
    return ((UDPServer*)This)->thread();
  };
 
public:
  UDPServer(int port);
  ClientManager &getClientManager();
  ~UDPServer();
};
 
 
//udpserver.cpp
#include "udpserver.h"
using namespace std;
UDPServer::UDPServer(int port)
{
  this->lport=port;
  gnet_init ();
  this->server=gnet_udp_socket_new_with_port(port);
  if (this->server == NULL)
    {
      fprintf (stderr, "Could not create server on port %d\n", port);
      exit (EXIT_FAILURE);
    }
  pthread_create( &serverthread, NULL, _run, this);
}
ClientManager &UDPServer::getClientManager()
{
return this->cm;
}
void* UDPServer::thread()
{
while (true)
  {
     gint bytes_received;
     std::string b;
     if (!gnet_udp_socket_has_packet(this->server))
    {
    sleep(1);
    continue;
    }
     bytes_received = gnet_udp_socket_receive (this->server, this->buffer, sizeof(this->buffer),&this->addr);
     b=this->buffer;
     b.erase(bytes_received);
     if (b.find("ch bin da"))
     {
       Client m;
       cm.registerClient(m);
     }
     printf("%s",b.c_str());
  }
}
UDPServer::~UDPServer() {
  pthread_join( serverthread, NULL );
}

Open in new window

Again, the only location where Client objects are created, is here :

>>        Client m;
>>        cm.registerClient(m);

Note that registerClient makes two copies of the object passed to it - one temporary copy, and one copy that is saved in the vector.
So, the local m object, and the temporary copy will be destroyed as soon as their context ends, and then the Client objects in the vector are destroyed as soon as the ClientManager object is destroyed.

So ... you should probably make sure that all those temporary objects are not created, and you should probably manage that vector a bit better.
Avatar of ktd85

ASKER

Hi,

is there any way to manage to vector without temporary objects?

thx
thomas
ASKER CERTIFIED SOLUTION
Avatar of Infinity08
Infinity08
Flag of Belgium image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial