473,804 Members | 2,147 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Inheritance and STL containers

I've ran into a problem with inheritance and STL containers. The code
is too much to list, but here is the basic problem:

#include <queue>

using namespace std;

class Base
{
public:
typedef queue<Base *BaseQ;

void DoBase(BaseQ &) {;} // should work on any queue of Base or a Base
subtype
};
class Derived: public Base
{
public:
typedef queue<Derived *DerivedQ;
};

// have other derived types from base: Derived1, Derived2, etc...

int main(int argc, _TCHAR* argv[])
{
Derived *dp = new Derived();
Base *bp(dp); // (A) this is legal as expected (upcasting)

Derived::Derive dQ dv; dv.push(dp);

bp->loopBase(dv) ; // (B) compiler says this is illegal, cannot convert
from queue<Derived *& to queue<Base *&
return 0;
}

If line (A) is legal, why isn't like (B) legal as well? There are
operations in Base that must apply to containers of any derived of
base. It seems wasteful to have to create a temporary queue<Base *and
load it with the contents of queue<Derived *to call loopBase()
(that's what I do now). Is there a better way?

Jul 27 '06 #1
9 2400
<mo********@yah oo.comwrote...
I've ran into a problem with inheritance and STL containers. The code
is too much to list, but here is the basic problem:

#include <queue>

using namespace std;

class Base
{
public:
typedef queue<Base *BaseQ;

void DoBase(BaseQ &) {;} // should work on any queue of Base or a Base
subtype
};
class Derived: public Base
{
public:
typedef queue<Derived *DerivedQ;
};

// have other derived types from base: Derived1, Derived2, etc...

int main(int argc, _TCHAR* argv[])
{
Derived *dp = new Derived();
Base *bp(dp); // (A) this is legal as expected (upcasting)

Derived::Derive dQ dv; dv.push(dp);

bp->loopBase(dv) ; // (B) compiler says this is illegal, cannot convert
from queue<Derived *& to queue<Base *&
return 0;
}

If line (A) is legal, why isn't like (B) legal as well?
sometemplate<Ta nd sometemplate<TT are *unrelated* types no matter
what relationship exists between T and TT. Unless they are the same,
any template instantiated from two different types produces two different
types as the result. No conversion exists between two different types
unless explicitly programmed (or part of the language, like int -double).
There are
operations in Base that must apply to containers of any derived of
base. It seems wasteful to have to create a temporary queue<Base *and
load it with the contents of queue<Derived *to call loopBase()
(that's what I do now). Is there a better way?
Just use 'queue<Base*>' and make sure you apply polymorphism there.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jul 27 '06 #2
Ah, I actually fuond a better solution: convert DoBase() to a template
function. Then it wil work:

#include <queue>

using namespace std;

class Base
{
public:
typedef queue<Base *BaseQ;

template <typename T>
void DoBase(queue<T& ) {;} // should work on any queue of Base or a
Base subtype
};
class Derived: public Base
{
public:
typedef queue<Derived *DerivedQ;
};

// have other derived types from base: Derived1, Derived2, etc...

int main(int argc, _TCHAR* argv[])
{
Derived *dp = new Derived();
Base *bp(dp); // (A) this is legal as expected (upcasting)

Derived::Derive dQ dv; dv.push(dp);

bp->DoBase<Deriv ed *>(dv); // (B) compiler says this is illegal,
cannot convert from queue<Derived *& to queue<Base *&

return 0;
}

Jul 27 '06 #3

Victor Bazarov wrote:
<mo********@yah oo.comwrote...

sometemplate<Ta nd sometemplate<TT are *unrelated* types no matter
what relationship exists between T and TT. Unless they are the same,
any template instantiated from two different types produces two different
types as the result. No conversion exists between two different types
unless explicitly programmed (or part of the language, like int -double).
Ok, this is what I try to understand. Why? There may be a good reason,
but I don't know. In by example,
Base *bp;
Derived *dp;
bp = dp; // this is legal and useful

why the compiler not use this convertion? Just trying to understand!

Jul 27 '06 #4
<mo********@yah oo.comwrote...
>
Victor Bazarov wrote:
><mo********@ya hoo.comwrote...

sometemplate<T and sometemplate<TT are *unrelated* types no matter
what relationship exists between T and TT. Unless they are the same,
any template instantiated from two different types produces two different
types as the result. No conversion exists between two different types
unless explicitly programmed (or part of the language, like int ->
double).
Ok, this is what I try to understand. Why?
I am not sure I understand the question... Why should they be related?
How would conversion work? Do you expect the conversion *implicit*? You
can program your own template containers which might provide conversions
from one to the other. My guess for the absence of the implicit conversion
is due to the inability to invent proper semantics for all cases.
There may be a good reason,
but I don't know. In by example,
Base *bp;
Derived *dp;
bp = dp; // this is legal and useful

why the compiler not use this convertion? Just trying to understand!
And do what? Would you expect the compiler to automatically convert
queue<Derived*t o queue<Base*or queue<Derived*t o queue<Base*>*
or queue<Derived>* to queue<Base>*? What for? Treat all elements of
the container of Derived as if they were Base? You can do it now. Or
something else? What would be the use?

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jul 27 '06 #5
mo********@yaho o.com wrote:
Victor Bazarov wrote:
><mo********@ya hoo.comwrote...

sometemplate<T and sometemplate<TT are *unrelated* types no matter
what relationship exists between T and TT. Unless they are the same,
any template instantiated from two different types produces two different
types as the result. No conversion exists between two different types
unless explicitly programmed (or part of the language, like int -double).
Ok, this is what I try to understand. Why? There may be a good reason,
but I don't know. In by example,
Base *bp;
Derived *dp;
bp = dp; // this is legal and useful

why the compiler not use this convertion? Just trying to understand!
Because they're separate types and there is no inheritance relationship
between them. Just imagine if there were an explicit specialization of
sometemplate<De rived>. Then it might look completely different than
sometemplate<Ba se>.
Jul 27 '06 #6

Victor Bazarov wrote:
There may be a good reason,
but I don't know. In by example,
Base *bp;
Derived *dp;
bp = dp; // this is legal and useful

why the compiler not use this convertion? Just trying to understand!

And do what? Would you expect the compiler to automatically convert
queue<Derived*t o queue<Base*or queue<Derived*t o queue<Base*>*
The conversion Derived * to Base * is available implicitly; my
queue<Base *>. I think it's reasonable to expect queue<Base *to be
assigned from a queue<Derived *>
or queue<Derived>* to queue<Base>*? What for? Treat all elements of
What for? For one, I could have a function in Base
Base::DoBase(qu eue<Base *&) operating on each Base *, but
polymorphism will let each derivation of Base in this queue morph the
behaviour as desired by that derivation. If another part of program has
a queue<Derived *>, but wants to call Base::DoBase with that queue as
the parameter, why not use the Derived * to Base * conversion that is
available?

Ok, 2nd part of my question is what is best solution. I posted a
solution (my last post of 7/27). If DoBase will invoke polymorphic
functions via Base *, then I could change the function declaration to:

template <typename T>
void DoBase(queue<T& ) {;}

How about this solution?

ps: Sorry my original post had a typo, the call to function loopBase is
not valid; it should call DoBase.

Jul 28 '06 #7
mo********@yaho o.com wrote:
[..] 2nd part of my question is what is best solution. I posted a
solution (my last post of 7/27). If DoBase will invoke polymorphic
functions via Base *, then I could change the function declaration to:

template <typename T>
void DoBase(queue<T& ) {;}

How about this solution?
This solution is not exactly the same. If you pass an object of type
'queue<Derived* >' to 'DoBase', 'T' will be deduced as 'Derived*', and
a new instantiation of 'DoBase' will be created. Any access to the
members of '*T' (Derived) will be made statically:

template <typename T>
void DoBase(queue<T& q) {
/* get the iterator */
(*it)->somemember() ; // here '*it' is of type 'Derived*'
}

(although it may not be as bad as it sounds).

What you might want to do is this:

void DoSingleBase(Ba se* pb) { /* something */ }

template <typename T>
void DoBase(queue<T& q) {
/* get the iterator */
DoSingleBase(*i t);
}

In this case the pointer that (*it) yields will be _converted_ to
to Base* and polymorphic behaviour will be ensured.

Or maybe I'm wrong. Try both and see.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jul 28 '06 #8

mo********@yaho o.com wrote:
The conversion Derived * to Base * is available implicitly; my
queue<Base *>. I think it's reasonable to expect queue<Base *to be
assigned from a queue<Derived *>
Maybe you think it is reasonable but it just doesn't work. The two
resultant classes are different and unrelated. It is something you'll
need to learn about templates. You can't copy/assign a queue<intto a
queue<longeithe r even though there is an implicit conversion. The
queue template would need copy/assignment operators that are templates
taking queue<Tas parameters; it doesn't and neither do any other std
containers that I am aware of.

I'm sure there are reasons why these operators where ommited from the
standard but I don't off hand know them. It is what it is.

Jul 28 '06 #9
mo********@yaho o.com wrote:
[conversion from queue<Derived*t o queue<Base*>]

This is in the FAQ:
http://www.parashift.com/c++-faq-lit....html#faq-21.3

and the questions surrounding it.

--
Marcus Kwok
Replace 'invalid' with 'net' to reply
Jul 31 '06 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

8
3154
by: Wolfgang Lipp | last post by:
<annotation> the first eleven contributions in this thread started as an off-list email discussion; i have posted them here with the consent of their authors. -- _w.lipp </annotation> From: Eric van der Vlist Sent: Tuesday, 27?January?2004 13:53 Hi,
12
2394
by: Glen Able | last post by:
Hello, I've been getting into the STL lately for personal projects and I'm can't decide whether to wrap containers or not. So the choice is whether to have a member variable like this: std::vector<Stuff> m_stuff; Or to wrap it in a 'StuffVector' class, encapsulating operations on the vector...
4
4032
by: KInd | last post by:
Hello All, When is nested class more preferable that Inheritance ? I think with proper inheritance and friend class concept we can get the same flexibility as nested classes Any comments .. Best Regards KInd --
19
3197
by: Mike Tyka | last post by:
Hello community, i'm fairly new to using the STL but i've been experimenting a bit with it. I tried to derive a new class say MyString from string like so: class MyString: public string{ public: MyString(){} };
2
2696
by: Søren Holstebroe | last post by:
Hi there, I'm having a struggle with GNU g++ (3.3.5) and inheritance of typedefs in STL containers. I'm trying to port some old code I wrote with MS Visual C++ and it looks like there is a discrepancy in the STL implementation or at least interpretation of the standard (I trust g++ most on the latter). To the case: While this compiles fine:
15
4102
by: Nindi73 | last post by:
HI If I define the class DoubleMap such that struct DoubleMap : public std::map<std::string, double>{}; Is there any overhead in calling std::map member functions ? Moreover are STL containers destructors virtual >
21
2222
by: George Exarchakos | last post by:
Hi everyone, I'd like your help... Can we have a std::list<BASEwhere BASE be the base class of a class hierarchy? I want to add to this list objects that are inherited from BASE class but not necessarily the same... class base { int x;
7
3795
by: wangxiaohu | last post by:
I am trying to write a class myVector based on std::vector and add only a sort method. The sort method needs to access the array stored in the base class using iterator. I have following draft code. However it never compile. Can anyone take a look and tell me how to fix it? Thanks! #include <vector> #include <iostream> using namespace std;
4
3964
by: EnsGabe | last post by:
Suppose you have a class heirarchy as such: class Base{ .... }; class Mid1 : public Base{ ....
0
9593
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 effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10595
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, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10343
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 tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10335
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
10088
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 protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
7633
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 presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6862
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 then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5529
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 last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5668
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?

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.