简体   繁体   中英

behavior of the compiler using classes

#include <list>
using std::list;
class foo { ...
class bar : public foo { ...
static void print_all(list<foo*> &L) { ...
list<foo*> LF;
list<bar*> LB;
...
print_all(LF); // works fine
print_all(LB); // static semantic error

I think i know why the compiler will not allow the second call. Can anyone give an example of bad things that could happen if the compiler accepts this kind of call?

Sure! What if print_all does this:

L.push_back(new Foo);

Now your list of Bar pointers has a pointer to a Foo object that is not a Bar. If you then try to call a method in Bar not present in the Foo class, you'll get some sort of serious runtime problem since the method doesnt exist in the Foo object.

Hope this helps!

There are two different things going on in the code, with different explanations. The first problem is that different instantiations of a template are unrelated, even if the instantiating types are related. In this particular case std::list<foo*> has no relationship with std::list<bar*> , even if foo is a base of bar . This is part of the design of the language and nothing can be done.

The second problem, which is not what the compiler is complaining about is that in general a container of derived cannot be used by reference as a container of base . That is the issue that @templatetypedef brought up --but again, this is not the issue in the code, it would be in a different example:

void f( base** p );
int main() {
   derived *d;
   f( &d );          // error
}

In this case, the issue is that, as @templatetypedef points out that using a pointer/container of derived in place of a pointer/container to base in a non-const manner is prone to errors, as you could store non- derived types on the pointer/container.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM