473,503 Members | 8,131 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Trying to downcast a class stored in vector from a function

4 New Member
Hi,

I created a vector like that" typedef std::vector<Client*> Clients" and declared a vector "Clients clients". I specialized the Client class to SpecialClient, so I have:

Expand|Select|Wrap|Line Numbers
  1.   class Client
  2.   {
  3.   public:
  4.     /// Constructor
  5.     Client (void); 
  6.     /// Destructor
  7.     virtual ~Client (void);
  8.     /// Register the client
  9.     virtual void show_info (char* name) ;
  10.     /// Get the name.
  11.     void  set_name (const char * name);
  12.   private:
  13.     std:string name;
  14. }
  15.  
  16.  
  17.   class SpecialClient
  18.   {
  19.   public:
  20.     /// Constructor
  21.     SpecialClient (void); 
  22.     /// Destructor
  23.     virtual ~SpecialClient (void);
  24.     /// Register the client
  25.     virtual void show_info (char* name) ;
  26.     /// Get the details.
  27.     void  set_details (const* char details);
  28.   private:
  29.     std:string details;
  30. }
  31.  
I declared the vector as
Expand|Select|Wrap|Line Numbers
  1. typedef std::vector<Client*> Clients;
  2. Clients clients;
  3.  
So I can store Client, SpecialClient and any other derived type of Client that I may need in the future.

My function populates the "clients" vector and return it to a calling program. So I have:

Expand|Select|Wrap|Line Numbers
  1. SpecialClient* cl = new SpecialClient();
  2. cl->set_name("Client1");
  3. cl->set_details("Details client 1");
  4. clients.push_back(cl);
  5.  
The function returns:
Expand|Select|Wrap|Line Numbers
  1.   Clients obtain_clients () {
  2.     return (clients);
  3. }
  4.  
In the main function I try to cast the vector elements to SpecialClient but it's not working correct.

Expand|Select|Wrap|Line Numbers
  1. Clients cls = obtain_clients();
  2. int index;
  3. for(index=0; index < cls.size(); index++) {
  4.   Client* cl = (cls.at(index));
  5.   std::string name = cl->get_name();
  6.   std::cout << "Name: " << name << std::endl;
  7.   SpecialClient * scl = dynamic_cast<SpecialClient*>(cl);
  8.   std::string details = scl->get_details();
  9.   std::cout << "Details: " << details << std::endl;
  10. }
  11.  
What happens is that the "name" is printed correctly but the "details" not. The cast occurs fine but the contect of the details member is not printed. I guess I'm missing some memory allocation but I can't figure out the problem. I'll appreciatte if you can help me.

Thank you.

Nei
Feb 22 '08 #1
4 2534
weaknessforcats
9,208 Recognized Expert Moderator Expert
First, stop casting.

Second, SpecialClient does not inherit from Client. SO this code:
SpecialClient* cl = new SpecialClient();
cl->set_name("Client1");
cl->set_details("Details client 1");
can't compile since SpecialClient does not have a set_name() method.

How are you getting this to run at all?
Feb 22 '08 #2
neisan
4 New Member
Sorry,

My mistake, I have:

Expand|Select|Wrap|Line Numbers
  1.  
  2.   class SpecialClient:Client
  3.  {
  4.   public:
  5.     /// Constructor
  6.     SpecialClient (void); 
  7.     /// Destructor
  8.     virtual ~SpecialClient (void);
  9.     /// Register the client
  10.     virtual void show_info (char* name) ;
  11.     /// Get the details.
  12.     void  set_details (const* char details);
  13.   private:
  14.     std:string details;
  15.   }
  16.  
What do you mean with stop casting? I have a vector that stores pointers to Client objects and need to access the SpecialClient members.

Thank you.
Feb 22 '08 #3
weaknessforcats
9,208 Recognized Expert Moderator Expert
What do you mean with stop casting? I have a vector that stores pointers to Client objects and need to access the SpecialClient members.
I mean stop casting.

If you have a SpecialClient object you can use its address as a Client address:
Expand|Select|Wrap|Line Numbers
  1. SpecialClient* s = new SpecialClient
  2. vector<Client*> clients;
  3. clients.push_back(s);
  4.  
No cast. A SpecialClient IS-A Client. Therefore, a SpecialClient pointer is a pointer to a Client.

Then when you:
Expand|Select|Wrap|Line Numbers
  1. Client* cl = (cls.at(index));
  2.  
and what you fetch is really a SpecialClass pointer then this code:
Expand|Select|Wrap|Line Numbers
  1. std::string name = cl->get_name();
  2.  
calls the get_name() of the Client object that is part of the SpecialClass object.

But this:
Expand|Select|Wrap|Line Numbers
  1. std::string details = scl->get_details();  //ERROR
  2.  
will never work since get_details is not a Client method.

The fundamental error here is that the interface is not fully defined in the Client base class. The cast is a hack to cover a design flaw.

You cannot add methods to a derived class and expect to call them using a base class.

The best solution is to properly design Client so all methods are in the Client.

You might also research separating the interface from the implementation. This will lead you to start using private virtual functions. Public virtual functions are a design no-no. That's because the clas should hide its implemenatation and a public function exposes it thereby breaking encapsulation.
Feb 23 '08 #4
neisan
4 New Member
Hi,

Thank you for your help. After putting all the code in one file and compiling it I realized that the problem I’m having is not because of the downcast. The problem is that I’m not being able to correct return the character and string values in the code. I’m sorry if I made you spend your time but I really appreciate the advices and information you provided. I’m trying now to solve the string manipulation problem.

Thank you again.

Nei


I mean stop casting.

If you have a SpecialClient object you can use its address as a Client address:
Expand|Select|Wrap|Line Numbers
  1. SpecialClient* s = new SpecialClient
  2. vector<Client*> clients;
  3. clients.push_back(s);
  4.  
No cast. A SpecialClient IS-A Client. Therefore, a SpecialClient pointer is a pointer to a Client.

Then when you:
Expand|Select|Wrap|Line Numbers
  1. Client* cl = (cls.at(index));
  2.  
and what you fetch is really a SpecialClass pointer then this code:
Expand|Select|Wrap|Line Numbers
  1. std::string name = cl->get_name();
  2.  
calls the get_name() of the Client object that is part of the SpecialClass object.

But this:
Expand|Select|Wrap|Line Numbers
  1. std::string details = scl->get_details();  //ERROR
  2.  
will never work since get_details is not a Client method.

The fundamental error here is that the interface is not fully defined in the Client base class. The cast is a hack to cover a design flaw.

You cannot add methods to a derived class and expect to call them using a base class.

The best solution is to properly design Client so all methods are in the Client.

You might also research separating the interface from the implementation. This will lead you to start using private virtual functions. Public virtual functions are a design no-no. That's because the clas should hide its implemenatation and a public function exposes it thereby breaking encapsulation.
Feb 25 '08 #5

Sign in to post your reply or Sign up for a free account.

Similar topics

2
1383
by: Steve Schlesinger | last post by:
In the following code I do a forced downcast of an A object to its derivative B If I declare all member variables in A and only add member functions in B, will this always work? The test...
2
3091
by: Chester | last post by:
Is it possible to new an object A, downcast it to B, and store B in a vector? I'm having problem with the following code: B is a derived class of A Blist.push_back( new B() ); Blist.push_back(...
11
1357
by: James Aguilar | last post by:
In the C++ STL, there are various places where you can call a function that takes a functor as a parameter. This functor may be either a function object or a function pointer. For instance, if...
8
12632
by: | last post by:
#include <iostream> using namespace std; class Base { public: Base() {} ~Base() {} };
11
1664
by: food4uk | last post by:
Dear all : I am not good at programming, please give a hand. My data structure is very similar as an array. I actually can use the std::vector as container to organize my data objects. However,...
6
1548
by: smoermeli | last post by:
#include <iostream> #include <vector> class Thing { private: int value; friend class Person; public: int getValue() { return value; } void...
4
3410
by: kungfuelmosan | last post by:
Hey guys, Im just getting into c++ at the moment so please bare with me Basically i need to declare a vector<stringstringArray(50) inside a class, however by doing so i am getting the following...
10
3569
by: Dom Jackson | last post by:
I have a program which crashes when: 1 - I use static_cast to turn a base type pointer into a pointer to a derived type 2 - I use this new pointer to call a function in an object of the...
9
2289
by: cronusf | last post by:
Why doesn't the following throw an exception. It seems like you should not be able to downcast from A to B since A is not a B. #include <iostream> using namespace std; class A { public:...
0
7207
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
7093
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
7291
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
7468
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
1
5023
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
4690
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
3180
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
1
748
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
402
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.