Path: utzoo!attcan!utgpu!jarvis.csri.toronto.edu!cs.utexas.edu!uunet!brunix!sdm From: sdm@cs.brown.edu (Scott Meyers) Newsgroups: comp.lang.c++ Subject: When polymorphic, when not? Message-ID: <22395@brunix.UUCP> Date: 7 Dec 89 19:12:10 GMT Sender: news@brunix.UUCP Reply-To: sdm@cs.brown.edu (Scott Meyers) Organization: Brown University Department of Computer Science Lines: 74 I'm having trouble figuring out under which conditions virtual functions are invoked polymorphically. Consider the following program, which has results shown for AT&T CC 2.0 and (where possible) g++ 1.36.2: 1 #include 2 3 struct B { virtual void foo() { cout << "B::foo\n"; }}; 4 struct D: public B { void foo() { cout << "D::foo\n"; }}; 5 6 void val(B p) { p.foo(); } 7 void ref(B &p) { p.foo(); } 8 9 main() { 10 { 11 D d; 12 B b; 13 14 b = d; 15 D &dr = d; 16 B &br = d; 17 18 val(b); // calls B::foo 19 val(br); // calls D::foo [g++ calls B::foo] 20 ref(b); // calls B::foo [g++ calls D::foo] 21 ref(br); // calls D::foo 22 23 val(d); // calls D::foo [g++ calls B::foo] 24 val(dr); // calls D::foo [g++ calls B::foo] 25 ref(d); // calls D::foo 26 ref(dr); // calls D::foo 27 } 28 29 // I don't know what results g++ gives for the following section 30 { 31 D d; 32 B b = d; // g++ won't compile this line ("unexpected argument 33 // to constructor `B'") 34 35 D &dr = d; 36 B &br = d; 37 38 val(b); // calls D::foo 39 val(br); // calls D::foo 40 ref(b); // calls D::foo 41 ref(br); // calls D::foo 42 43 val(d); // calls D::foo 44 val(dr); // calls D::foo 45 ref(d); // calls D::foo 46 ref(dr); // calls D::foo 47 } 48 } Why are the results of lines 18 and 20 different from lines 38 and 40? Who is right for lines 19, 20, 23, 24 -- CC or g++? How is it possible for function val, which takes a B as an argument (not a pointer to a B or a reference to a B) to ever call anything other than B::foo? Does either of the compilers exhibit any bugs in this example? Is there a simple set of consistent rules that will allow me to predict what's going to happen in cases like this? That is, if I have a function f with a formal parameter p and I pass object o to f as the actual parameter, can I predict which functions will be invoked on p given: - The type of o (e.g., simple object, reference to an object, or pointer to an object) - The type of p (e.g., simple object, reference, or pointer) Scott sdm@cs.brown.edu