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? 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
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;
}
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!
<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 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>.
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. 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 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. This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
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,
|
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...
|
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
--
|
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(){}
};
|
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:
| |
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 >
|
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;
|
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;
|
by: EnsGabe |
last post by:
Suppose you have a class heirarchy as such:
class Base{
....
};
class Mid1 : public Base{
....
|
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,...
|
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...
| |
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...
|
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,...
|
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...
|
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...
|
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();...
|
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...
| |
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
| |