Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

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

Posted on 2009-04-26
19
Medium Priority
?
284 Views
Last Modified: 2012-08-13
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

0
Comment
Question by:ktd85
  • 10
  • 9
19 Comments
 
LVL 53

Expert Comment

by:Infinity08
ID: 24235495
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.).
0
 
LVL 2

Author Comment

by:ktd85
ID: 24235503

//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

0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24235506
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).
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 53

Expert Comment

by:Infinity08
ID: 24235512
btw, the code you posted is not the same code you posted earlier - it doesn't contain the printf ...
0
 
LVL 2

Author Comment

by:ktd85
ID: 24235520
oh, sorry. i modified...
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24235524
So, does that solve your problem ? If not, can you post the new code, as well as the new error message you get ?
0
 
LVL 2

Author Comment

by:ktd85
ID: 24235531
Corrected the ()-thing.
Is there a method to return the referenc to the original object?
Do have to change the function-call?
0
 
LVL 2

Author Comment

by:ktd85
ID: 24235551
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?
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24235569
>> 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

0
 
LVL 2

Author Comment

by:ktd85
ID: 24235589
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();  
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24235595
>> 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).
0
 
LVL 2

Author Comment

by:ktd85
ID: 24235612
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

0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24235646
>> 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 ...
0
 
LVL 2

Author Comment

by:ktd85
ID: 24235661
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?
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24235663
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 ?
0
 
LVL 2

Author Comment

by:ktd85
ID: 24235696
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

0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24236354
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.
0
 
LVL 2

Author Comment

by:ktd85
ID: 24236970
Hi,

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

thx
thomas
0
 
LVL 53

Accepted Solution

by:
Infinity08 earned 500 total points
ID: 24237035
We're going a bit off topic here, as this is no longer related to your original question. If your original question has been answered, you should close this question. If you have further questions, you can create new question(s) for them.

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

pass by reference will help. Storing pointers in the vector rather than objects, might help too ...
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
  Included as part of the C++ Standard Template Library (STL) is a collection of generic containers. Each of these containers serves a different purpose and has different pros and cons. It is often difficult to decide which container to use and …
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.
Suggested Courses

810 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question