By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,188 Members | 965 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,188 IT Pros & Developers. It's quick & easy.

STL list related

P: n/a
Hi,

why cant a list<derived*be implicitly castable to list<base*>?

Any alternatives other than global operators?

thanks in advance,
Naren.

Nov 8 '06 #1
Share this Question
Share on Google+
9 Replies


P: n/a
Hi Naren,

Firstly list<base*is different from list<derived*>, there is no
inheritance which is linking these.

If you want to use both derived class and base class pointer in a
common list, then in that case you can consider keeping derived* in
list<base*container.

To make it more clear, consider the following example.

list<derived*dList;
list<base*>& refBList = dList; //ERROR. Let's assume this would work
for now
refBList.push_back(new base());
//Now dList containes a pointer to base*...PROBLEM

Regards
- Amit Gupta

Naren wrote:
Hi,

why cant a list<derived*be implicitly castable to list<base*>?

Any alternatives other than global operators?

thanks in advance,
Naren.
Nov 8 '06 #2

P: n/a


On Nov 8, 8:52 am, "Naren" <narendranath.thad...@gmail.comwrote:
why cant a list<derived*be implicitly castable to list<base*>?
list<derived*doesn't inherit from list<base*>

What is it that you trying to accomplish?
Any alternatives other than global operators?
How would a global operator accomplish what you are trying to do?

Nov 8 '06 #3

P: n/a

Naren wrote:
Hi,

why cant a list<derived*be implicitly castable to list<base*>?
http://www.parashift.com/c++-faq-lit....html#faq-21.3

Gavin Deane

Nov 8 '06 #4

P: n/a


Gavin Deane wrote:
Naren wrote:
>>Hi,

why cant a list<derived*be implicitly castable to list<base*>?


http://www.parashift.com/c++-faq-lit....html#faq-21.3
I'm not following here. The containers are of pointers, not objects. (I
assume the objects are created on the heap.)

How would this be wrong?:

struct F
{
long value;
virtual ~F( ) { }
};

struct E : public F
{
long value2;
virtual ~E( ) { }
};

main(...)
{
std::vector<E*eVect;
eVect.push_back( new E );
eVect.front( )->value2= 10;

std::vector<F*fVect;
fVect.push_back( eVect.front( ) );

std::cout << dynamic_cast<E*>( fVect.front( ) )->value2 << '\n';
}
Gavin Deane
It works.
Thanks, Dan.

Nov 8 '06 #5

P: n/a

Dan Bloomquist wrote:
Gavin Deane wrote:
Naren wrote:
>Hi,

why cant a list<derived*be implicitly castable to list<base*>?

http://www.parashift.com/c++-faq-lit....html#faq-21.3

I'm not following here. The containers are of pointers, not objects. (I
assume the objects are created on the heap.)
The containers have to be of pointers not objects otherwise there is no
polymorphism involved at all and the question can't even arise.
How would this be wrong?:
<snip code that contains a dynamic cast from base* to derived*>
Your example is not what the OP, or the FAQ I pointed to, is talking
about.

The OP wants to be able to convert implicitly from a list<derived*to
a list<base*>. The point in the FAQ is that, if Fruit is the base class
and Apple and Orange are two classes derived from Fruit, converting a
container of Apples to a container of Fruit would allow you to put an
Orange in the container of Apples. Implicit in that is that the
containers hold pointers, not objects. It is only possible to have the
concept of a container of Fruit holding Apples if the stored type is a
pointer. The OP's question was about containers of pointers.

#include <list>
using std::list;

class base { /* ... */ };

class derived1 : public base { /* ... */ };

class derived2 : public base { /* ... */ };

void f(list<base*>& bl)
{
// This is OK. derived1 and derived2 both derive
// from base so both can be pointed to by a base*
bl.push_back(new derived1);
bl.push_back(new derived2);
}

int main()
{
list<base*base_list;
f(base_list);
// base_list now contains two pointers. The first
// points to a derived1, the second points to a
// derived2.

// The first push_back is OK
// The second won't compile because d1_list
// is a list of derived1* not a list of derived2*
list<derived1*d1_list;
d1_list.push_back(new derived1);
d1_list.push_back(new derived2);

list<derived1*another_d1_list;
// The OP wants to be able to do this somehow
f(another_d1_list);
// If the above were possible, what should happen
// when function f tries to put a derived2* in
// this list of derived1*? That would be
// equivalent to the statement above that quite
// sensibly does not compile.
}

Also have a look at the rest of FAQ 21.

Gavin Deane

Nov 9 '06 #6

P: n/a


Gavin Deane wrote:
>
<snip code that contains a dynamic cast from base* to derived*>
Your example is not what the OP, or the FAQ I pointed to, is talking
about.

The OP wants to be able to convert implicitly from a list<derived*to
a list<base*>. The point in the FAQ is that, if Fruit is the base class
and Apple and Orange are two classes derived from Fruit, converting a
container of Apples to a container of Fruit would allow you to put an
Orange in the container of Apples. Implicit in that is that the
containers hold pointers, not objects. It is only possible to have the
concept of a container of Fruit holding Apples if the stored type is a
pointer. The OP's question was about containers of pointers.
Hi Gavin,
Thanks for the time. I am really trying to understand what I'm missing.
>
#include <list>
using std::list;

class base { /* ... */ };

class derived1 : public base { /* ... */ };

class derived2 : public base { /* ... */ };

void f(list<base*>& bl)
{
// This is OK. derived1 and derived2 both derive
// from base so both can be pointed to by a base*
bl.push_back(new derived1);
bl.push_back(new derived2);
}
Good! I've done that several times so as to keep an assortment of objects.
int main()
{
list<base*base_list;
f(base_list);
// base_list now contains two pointers. The first
// points to a derived1, the second points to a
// derived2.

// The first push_back is OK
// The second won't compile because d1_list
// is a list of derived1* not a list of derived2*
list<derived1*d1_list;
d1_list.push_back(new derived1);
d1_list.push_back(new derived2);
Yes.
>
list<derived1*another_d1_list;
// The OP wants to be able to do this somehow
f(another_d1_list);
// If the above were possible, what should happen
// when function f tries to put a derived2* in
// this list of derived1*? That would be
// equivalent to the statement above that quite
// sensibly does not compile.
Ok, the op wrote:
why cant a list<derived*be implicitly castable to list<base*>?
And I've reread the faq. Now I get it.

I would have never thought of doing it and misunderstood, I guess that's
a good thing. To be sure, he wants to treat the derived* like a base*,
not just grab the derived by the base.
Gavin Deane
Thanks, Dan.

Nov 10 '06 #7

P: n/a
Dan Bloomquist wrote:
Gavin Deane wrote:

<snip code that contains a dynamic cast from base* to derived*>
Your example is not what the OP, or the FAQ I pointed to, is talking
about.

The OP wants to be able to convert implicitly from a list<derived*to
a list<base*>. The point in the FAQ is that, if Fruit is the base class
and Apple and Orange are two classes derived from Fruit, converting a
container of Apples to a container of Fruit would allow you to put an
Orange in the container of Apples. Implicit in that is that the
containers hold pointers, not objects. It is only possible to have the
concept of a container of Fruit holding Apples if the stored type is a
pointer. The OP's question was about containers of pointers.

Hi Gavin,
Thanks for the time. I am really trying to understand what I'm missing.

#include <list>
using std::list;

class base { /* ... */ };

class derived1 : public base { /* ... */ };

class derived2 : public base { /* ... */ };

void f(list<base*>& bl)
{
// This is OK. derived1 and derived2 both derive
// from base so both can be pointed to by a base*
bl.push_back(new derived1);
bl.push_back(new derived2);
}

Good! I've done that several times so as to keep an assortment of objects.
int main()
{
list<base*base_list;
f(base_list);
// base_list now contains two pointers. The first
// points to a derived1, the second points to a
// derived2.

// The first push_back is OK
// The second won't compile because d1_list
// is a list of derived1* not a list of derived2*
list<derived1*d1_list;
d1_list.push_back(new derived1);
d1_list.push_back(new derived2);

Yes.

list<derived1*another_d1_list;
// The OP wants to be able to do this somehow
f(another_d1_list);
// If the above were possible, what should happen
// when function f tries to put a derived2* in
// this list of derived1*? That would be
// equivalent to the statement above that quite
// sensibly does not compile.

Ok, the op wrote:
why cant a list<derived*be implicitly castable to list<base*>?
And I've reread the faq. Now I get it.

I would have never thought of doing it and misunderstood, I guess that's
a good thing. To be sure, he wants to treat the derived* like a base*,
not just grab the derived by the base.
Gavin Deane

Thanks, Dan.
Thanks EveryBody.

I do undrstand that we cannot do for the same reason which you guys
have mentioned.
but just wanted to know if you guys have encountered it in design.
Let's say an Entity A "has a relationship" with a group of Entity C.
Entity C "is a" Entity B.
Entity D requires to work on a group of constant Entity B(D does not
change group of Bs)
Now from "A" "D" can only get a group of C, but logically they could
have been treated as group of Bs. So I just wanted to know if there is
any better method rather than tweking A and making it hold a group of
Bs.

In C++ terms
class B
{};
class A
{
list<C*x;
};
class C: public B
{
};
class D
{
func(const list<B*>& a);
};

int main()
{
A p;
D k;
k.func(p.GetList());
}

To make it work change A to
class A
{
list<B*x;
};

Though logically A does not really hold items of type B and func does
not change the list.

Thanks in advance.

Rgds,
Naren.

Nov 13 '06 #8

P: n/a
Naren schreef:
Hi,

why cant a list<derived*be implicitly castable to list<base*>?
Because the first cannot contain AnotherDerived*, and the second can.

Now, consider this function:
void foo(list<base*>& BaseList) {
static AnotherDerived object;
BaseList.push_back(&object);
}

HTH,
Michiel Salters

Nov 13 '06 #9

P: n/a


Naren wrote:
>
In C++ terms
class B
{};
class A
{
list<C*x;
};
class C: public B
{
};
class D
{
func(const list<B*>& a);
};

int main()
{
A p;
D k;
k.func(p.GetList());
}

To make it work change A to
class A
{
list<B*x;
};

Though logically A does not really hold items of type B and func does
not change the list.
Here I would say, 'But it does'. And considering the design of a more
complete program, where would these 'C' objects have come from? Where
would they be fundamentally stored? Why did you derive 'C' from 'B'?

When it comes time to destroy these objects they should all be kept in
some general 'B' container or you could have an object management nightmare.

I don't see how in the real world it should not be necessary to keep a
container of 'C'. A container of 'B' that is known to be 'C' might make
more sense. How about:

struct A
{
virtual ~A( ) { }
};

struct B : A
{
};

struct VB : std::vector<A*>
{
B* operator [ ] ( int i )
{
assert( dynamic_cast<B*>( at( i ) ) );
return dynamic_cast<B*>( at( i ) );
//or return a null if not castable
}
};

and then you can:
VB vb;
B* b= vb[i];
or:
A* a= vb[i];

Best, Dan.

Nov 13 '06 #10

This discussion thread is closed

Replies have been disabled for this discussion.