473,387 Members | 1,942 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

Inheritance and casting

I am writing a queue object that will take different types of values. My approach is to have the std::queue take objects of a base class type while the user interacts with the queue using objects derived from the base type. Here is the relevant code:

inside Queue.h
Expand|Select|Wrap|Line Numbers
  1.    class RequestObject
  2.    {
  3.      public:
  4.       // Constructor
  5.       RequestObject(){ mType = -1; }
  6.       virtual ~RequestObject(){}
  7.  
  8.       int GetType() const { return mType; }
  9.       void SetType(int i) { mType = i; }
  10.  
  11.      private:
  12.       int mType;
  13.    };
  14.  
  15.    class IntDoublePair : public RequestObject
  16.    {
  17.       public:
  18.          IntDoublePair(){ mInt = 0; mDouble = 0.0; }
  19.          IntDoublePair(int i, double d){ mInt = i; mDouble = d; }
  20.          IntDoublePair(RequestObject O){}
  21.          virtual ~IntDoublePair(){}
  22.  
  23.          void SetInt(int value){ mInt = value; }
  24.          void SetDouble(double value){ mDouble = value; }
  25.          int GetInt(){ return(mInt); }
  26.          double GetDouble(){ return(mDouble); }
  27.       private:
  28.          int    mInt;
  29.          double mDouble;
  30.    };
  31.  
  32.    class QueueObject
  33.    {
  34.    public:
  35.        QueueObject(){}
  36.        ~QueueObject(){}
  37.  
  38.        // Public Methods
  39.        void Add(const RequestObject &Request);
  40.        bool Empty();
  41.        RequestObject Pop();
  42.        void Clear();
  43.  
  44.    private:
  45.        std::queue<RequestObject> Q;
  46.    };
  47.  
Inside Queue.cpp
Expand|Select|Wrap|Line Numbers
  1. #include "Queue.h"
  2.  
  3. using namespace std;
  4.  
  5. void QueueObject::Add(const RequestObject &Request)
  6. {
  7.    RequestObject O = Request;
  8.     Q.push(O);
  9. }
  10.  
  11. RequestObject QueueObject::Pop()
  12. {
  13.     RequestObject O = Q.front();
  14.     Q.pop();
  15.     return(O);
  16. }
  17.  
  18. bool QueueObject::Empty()
  19. {
  20.    return(Q.empty());
  21. }
  22.  
  23. void QueueObject::Clear()
  24. {
  25.    while(!Q.empty())
  26.    {
  27.       Q.pop();
  28.    }
  29. }
  30.  
Inside QueueTest.cpp
Expand|Select|Wrap|Line Numbers
  1. #include <iostream>
  2. #include "Queue.h"
  3.  
  4. using namespace std;
  5.  
  6. int main(int argc, char *argv[])
  7. {
  8.    QueueObject mQ;
  9.  
  10.    for(int i = 0; i < 10; ++i)
  11.    {
  12.       IntDoublePair tID(i, (i*1000.0/10.0));
  13.       tID.SetType(i);
  14.       mQ.Add(tID);
  15.    }
  16.  
  17.    while(!mQ.Empty())
  18.    {
  19.       IntDoublePair ip = mQ.Pop();
  20.       cout << "Int = " << ip.GetInt() <<
  21.               " Doub = " << ip.GetDouble() << 
  22.               " Type = " << ip.GetType() << endl;
  23.    }
  24.  
  25.    return(0);
  26. }
  27.  
Unfortunately the output of this test code is:

Int = 9 Doub = 900 Type = -1
Int = 9 Doub = 900 Type = -1
Int = 9 Doub = 900 Type = -1
Int = 9 Doub = 900 Type = -1
Int = 9 Doub = 900 Type = -1
Int = 9 Doub = 900 Type = -1
Int = 9 Doub = 900 Type = -1
Int = 9 Doub = 900 Type = -1
Int = 9 Doub = 900 Type = -1
Int = 9 Doub = 900 Type = -1

where it should be:
Int = 0 Doub = 0 Type = 0
Int = 1 Doub = 100 Type = 1
Int = 2 Doub = 200 Type = 2
Int = 3 Doub = 300 Type = 3
Int = 4 Doub = 400 Type = 4
Int = 5 Doub = 500 Type = 5
Int = 6 Doub = 600 Type = 6
Int = 7 Doub = 700 Type = 7
Int = 8 Doub = 800 Type = 8
Int = 9 Doub = 900 Type = 9

So I have two questions:

Has anyone already implemented anything like this?

If not, does anyone have an idea of why this code is not behaving as expected?

Thanks.
Aug 6 '08 #1
6 1987
boxfish
469 Expert 256MB
Hi,
Since your QueueObject's Q is a <RequestObject> queue, it can't hold the IntDoublePairs, even though they're descended from RequestObject. Only dynamic variables can hold the descendants of their type. In order to do this, you will need to make Q a <RequestObject*> queue, and dynamically allocate memory for the RequestObjects you put into it.
Hope this helps.
Aug 6 '08 #2
Savage
1,764 Expert 1GB
That is,you can only call object methods declared in base class. Everything else will result in pure garbage. Making your queue class a template class,or adding methods from IntDoublePair to base class should give you expected results.
Aug 6 '08 #3
Thanks for both replies.

I've toyed around with the idea of making the Queue class a template but I'm not very proficient with templates and the trouble I have come across is that while the std::queue is a template class, it only takes in one type of object for each instance.

I'm not sure if it is possible to make a single std::queue object hold objects of different types. Any ideas on this thought? In my case this is what I try to emulate but again, I'm not familiar enough with templates and that might be the problem here.
Aug 6 '08 #4
Savage
1,764 Expert 1GB
Thanks for both replies.

I've toyed around with the idea of making the Queue class a template but I'm not very proficient with templates and the trouble I have come across is that while the std::queue is a template class, it only takes in one type of object for each instance.

I'm not sure if it is possible to make a single std::queue object hold objects of different types. Any ideas on this thought? In my case this is what I try to emulate but again, I'm not familiar enough with templates and that might be the problem here.
There are three good ways to go about it then:

1.Use boxfish's way and make your self responsible for managing memory.
2.Make your base class use a universal accessor:

Expand|Select|Wrap|Line Numbers
  1. class Base
  2. {
  3.   protected:
  4.   /*........*/
  5.  
  6.   public:
  7.  
  8.   /*Universal accessors,each class implements this pair of accessors..*/
  9.   virtual void SetValue(void* value);
  10.   virtual void *GetValue(void);
  11.  
  12. };
  13.  
Not very type safe,the one of reasons templates exist.

3.Use template base class:

Expand|Select|Wrap|Line Numbers
  1. template<class T>
  2. class Base
  3. {
  4.   protected:
  5.   /*...............*/
  6.  
  7.  
  8.   public:
  9.  
  10.    virtual void Set(T &value);
  11.    virtual T Get(void);
  12.  
  13. };
Type safer,but includes messy templates syntax
Aug 6 '08 #5
weaknessforcats
9,208 Expert Mod 8TB
I thnk you are being steered the wrong way.

True: Your queue must contain pointers or references to the base class.
True: Using the base class reference in the queue you can only call methods on RequestObject
FALSE: You have to put derived class methods into RequestObject.
FALSE: There is no way to call IntDoublePair methods using a RequestObject.

That is, the base class contains the interface to the hierarchy and does not mean that all the methods in the derived class have to be in the base class as virtual functions.

Almost cetainly, the the virtual methods in the base and derived classes need to be private. Virtual describes the implementation. You are to separate the intrerface from thje implementation (you might Google this phrase).

Read this article about that: http://bytes.com/forum/thread793836.html.

Then to access those derived class methods that aren't in the base class, you need a Visitor. This is a design pattern that will solve your problem. Read this: http://bytes.com/forum/thread674645.html.
Aug 6 '08 #6
I thnk you are being steered the wrong way.

True: Your queue must contain pointers or references to the base class.
True: Using the base class reference in the queue you can only call methods on RequestObject
FALSE: You have to put derived class methods into RequestObject.
FALSE: There is no way to call IntDoublePair methods using a RequestObject.

That is, the base class contains the interface to the hierarchy and does not mean that all the methods in the derived class have to be in the base class as virtual functions.

Almost cetainly, the the virtual methods in the base and derived classes need to be private. Virtual describes the implementation. You are to separate the intrerface from thje implementation (you might Google this phrase).

Read this article about that: http://bytes.com/forum/thread793836.html.

Then to access those derived class methods that aren't in the base class, you need a Visitor. This is a design pattern that will solve your problem. Read this: http://bytes.com/forum/thread674645.html.
Thanks for the tip on the articles. I had never heard of the Visitor concept (I'm a programmer by need :). It is taking me a bit of time to wrap my head around the concept but I think I agree with you that it would solve the problem I am having.

Thanks!
Aug 8 '08 #7

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

Similar topics

6
by: Stuart Golodetz | last post by:
Hi, I've got a minor casting issue which I need to check about (marked // <--). I was trying to do a static_cast on it (which didn't work, though I'm not sure why this should be the case?) I...
4
by: Kevin L | last post by:
Below is a code snippet that fails to compile under vc.net class BaseInterface { public: virtual void f() = 0; }; class BaseImplementation : public BaseInterface {
10
by: Jakob Bieling | last post by:
Hi, Suppose I have a base class and a derived class as follows: class base { public: void somefunc (); };
22
by: Matthew Louden | last post by:
I want to know why C# doesnt support multiple inheritance? But why we can inherit multiple interfaces instead? I know this is the rule, but I dont understand why. Can anyone give me some concrete...
12
by: Mike | last post by:
I want to provide an abstract class to derive all nodes from. In the example below Parent in the base class is of Type Node, but in the custom class I want Parent to return a Type CustomNode. When...
6
by: apm | last post by:
Recently I have had to use a value type for a complex structure because I don't know how to override the = operator. Can the operator ever be overloaded? Or can inheritance be used with value types?
1
by: vinoraja | last post by:
There are a number of reasons we don't implement Multiple Implementation Inheritance directly. (As you know, we support Multiple Interface Inheritance). However, I should point out that it's...
18
by: bsruth | last post by:
I tried for an hour to find some reference to concrete information on why this particular inheritance implementation is a bad idea, but couldn't. So I'm sorry if this has been answered before....
3
by: Leo Seccia | last post by:
Hello everyone, I have a c# project with a sql server database. I have a number of lookup tables in my database which I successfully managed to import into my LINQ dataclasses. eg. Table:...
1
by: Eric | last post by:
Let's say I have a base class that implements IComparable<baseClass>. Really it could be any interface but I'm picking that one for the sake of discussion. In this class, equality and comparisons...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
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
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
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

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.