Download presentation
Presentation is loading. Please wait.
Published byGriselda Harvey Modified over 9 years ago
1
C++ Training Datascope Lawrence D’Antonio Lecture 6 An Overview of C++: What is Polymorphism? - Coercion
2
What is polymorphism? Different types of objects respond to the same message and use the appropriate method. Polymorphism Universal Ad-hoc Parametric Subtype Overloading Coercion
3
A coercion is an implicit type conversion. This allows the programmer to omit a type cast. There are three types of coercions: Compiler defined (such as promotions, derived base) Constructor User defined
4
Compiler defined coercions Simple example double x; x = 2; //2 promoted to double
5
Function call coercions void foo(double x) { //... } //foo() can be called with any type that can be //converted to double foo((short) 4); foo(‘a’); foo(3L); foo(2.3F);
6
Is this legal? #include void f(char a, int b) { std::cout << a << b << '\n'; } void f(int a, char b) { std::cout << a << b << '\n'; } main() { f('a','b'); return 0; }
7
Not legal, it’s ambiguous.
8
Coercion vs. Overloading example 3 + 4; 3 + 4.0; 3.0 + 4; 3.0 + 4.0; How does this work?
9
Explanations of example Four overloaded versions of operator + Two overloaded versions of operator +, one for integers, the other for doubles. The middle two calls in the example would use coercion. One version of operator +, for doubles. The first three calls in the example would use coercion.
10
Derived to Base Conversion C++ will implicitly convert a pointer or reference to a derived class to a pointer or reference to the base class. This is because the derived class has a copy of the base class inside it. A pointer to the base class cannot be converted to a pointer to the derived class.
11
Is this legal? class A {}; class B: public A {}; class C: protected A {}; class D: private A {}; main() { A *pa = new B; pa = new C; pa = new D; return 0; }
12
pa = new B; //Legal, B is an A pa = new C; //Illegal, C is not an A pa = new D; //Illegal, D is not an A In the last two cases, the base class is inaccessible.
13
Is this legal? class A {}; class C: protected A { public: void foo() { A *pa = this; } }; class D: private A { public: void foo() { A *pa = this; } }; main() { C c; c.foo(); D d; d.foo(); return 0; }
14
Yes, it’s legal. Protected and private inheritance exemplify a has-a relationship, rather than an is-a relationship. Member functions are allowed to convert pointer to derived into pointer to base.
15
Pointer to Member Conversions What is the relationship between a pointer to member of a base class and a derived class?
16
Is this legal? struct A { int a; }; struct B: public A { int a; }; main() { A a; B b; int A::*pa = &B::a; int B::*pb = &A::a; return 0; }
17
Complicated. int A::*pa = &B::a; is illegal. Can’t convert pointer to derived member to a pointer to base member. int B::*pb = &A::a; Is legal. Can convert pointer to base member to a pointer to derived member.
18
Conversion Constructors Constructors that take a single argument can be thought of as a type conversion. struct X { X(int); }; So that any code that expects an object of class X can be passed an int that will then be converted to an X.
19
Is this legal? struct X { X(int){} }; void f(const X &) {} void g(int) {} void g(X) {} main() { f(3); g(4); g(X(5)); return 0; }
20
f(3); //Legal, you can create a temp //object X(3), which is passed to //f() g(4); //Legal, calls g(int) g(X(5)); //Legal, calls g(X)
21
Is this legal? struct X { X(int){} }; void f(X &) {} void g(int) {} void g(X) {} main() { int a = 2; f(3); f(a); g(4); g(X(5)); return 0; }
22
f(3); //Not legal, can’t use temp X object to initialize an X & f(a); //Not legal, can’t use temp X object to initialize an X & g(4); //Legal, as before g(X(5)); //Legal, as before
23
Is this legal? struct X { X(int){} }; struct Y { Y(X) {} }; void f(Y) {} main() { f(3); return 0; }
24
Not legal. Basically, only one level conversions are allowed. Not allowed to convert int to X to Y.
25
Is this legal? struct X { X(int){} }; void f(X) {} void g(int) {} void g(X) {} main() { int a = 2; f(3); f(a); g(4); g(X(5)); return 0; }
26
f(3); //Legal, temp X is passed by value f(a); //Legal, temp X is passed by value g(4); //Legal, as before g(X(5)); //Legal, as before
27
Is this legal? class X { public: X() { std::cout << "Hello\n"; } void foo() { std::cout << "In X::foo()\n"; } }; class Y { X ex; public: Y(X x): ex(x) { std::cout << "World\n"; } void foo() { ex.foo(); } void foo(X x) { x.foo(); } void foo(Y y) { y.foo(); } }; main() { Y y(X()); y.foo(y); return 0; }
28
Not legal! The problem is y.foo(y). foo is not a member of y, which is of non- class type Y ()(X (*)()). This can be fixed with Y y = X();
29
Explicit Constructors Single argument constructors (or constructors that can be called with a single argument) can lead to unexpected consequences.
30
class X { int x; public: X(int a = 0):x(a) {} }; main() { X ptr_x = 0; //...
31
That was bad! The programmer probably meant X *ptr_x = 0; But the compiler performed the conversion X ptr_x = X(0);
32
Solution class X { int x; public: explicit X(int a = 0):x(a) {} }; main() { X ptr_x = 0; //...
33
The compiler will flag the following as an error: X ptr_x = 0; This code implicitly uses the constructor X(int) In order to use this constructor, one must explicitly call the constructor. X ptr_x = X(0);
34
Constructor Rule Any single argument constructor should be declared explicit.
35
Conversion operators A user defined operator that converts a user defined object into another type. The destination type may be a built-in or user defined type.
36
Example class Fraction { int numerator, denominator; public: Fraction(int n = 0, int d = 1): numerator(n), denominator(d) {} //... operator double() const { return static_cast (numerator)/denominator; } };
37
Usage Fraction f(3,4); double d = f; // d is 0.75 double x = f + 2;
38
Is this legal? Fraction f(1,2), g(1,3); Fraction h; h = f + g;
39
Hard to tell! h = f + g; This is legal if there is an overloaded operator + that takes Fraction operands. This is also legal if, in the unlikely case, there was a ctor Fraction(double).
40
Perils of conversion template class Ptr { T *p; public: //... operator bool() const { return p ? true : false; } }; Ptr ptr1; Ptr ptr2; if (ptr1 == ptr2) {/...}
41
The comparison ptr1 == ptr2 is valid because the Ptr s are converted into bools and then compared. So Apples and Oranges can be compared! If operator == were overloaded for type Ptr, then that version would be called.
42
Is this legal? string filename = “data.txt”; ifstream in_file(filename);
43
Not legal! ifstream constructor expects a const char * argument. Legal version: ifstream in_file(filename.c_str());
44
Is this legal? //Let’s define a conversion operator for // string class operator const char*(const string &s) { return s.c_str(); } string filename = “data.txt”; ifstream in_file(filename);
45
Not legal! Conversion operators can only be member functions.
46
C++ is weakly typed class Tupid { public: template operator X { return X(); } };
47
This means that objects of class T can be converted into an object of any (yes, any) type that has a default constructor. Tupid t; int a = t; string s = t; vector v = t;
48
Breaking encapsulation class A { public: void foo() {}; } ; class D: private A { public: A *foo() { A *pa = this; return pa; } }; main() { D d; A *pa = d.foo(); pa->foo(); //Calls A::foo //...
49
Breaking encapsulation 2 class A { int a; public: int *foo() { return &a; } }; main() { A a; int *p = a.foo(); *p = 12;
50
Breaking encapsulation 3 class A { private: int a; }; class B: public A {}; main() { A a; B b; int B::*pb = &A::a; b.*pb = 5; return 0; }
51
Not legal. A::a accesses private data
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.