Upload
others
View
3
Download
0
Embed Size (px)
Citation preview
14: Inheritance & Composition
김동원김동원김동원김동원
2003.05.19
Thinking in C++ Page 1
Overview
• Operator overloading & inheritance
• Multiple inheritance
• Upcasting
Thinking in C++ Page 2
Operator overloading & inheritance
• Operator overloading & inheritance
Thinking in C++ Page 3
Operator overloading & inheritance
• Except for the assignment operator, operators are automatically inherited into a derived class
Thinking in C++ Page 4
Operator overloading & inheritance (example)
//: C14:OperatorInheritance.cpp
// Inheriting overloaded operators
#include "../C12/Byte.h"
#include <fstream>
using namespace std;
ofstream out("ByteTest.out");
class Byte2 : public Byte {
public:
// Constructors don't inherit:
Byte2(unsigned char bb = 0) : Byte(bb) {}
// operator= does not inherit, but
// is synthesized for memberwise assignment.
// However, only the SameType = SameType
// operator= is synthesized, so you have to
// make the others explicitly:
Thinking in C++ Page 5
Operator overloading & inheritance (example)
Byte2& operator=(const Byte& right)
{
Byte::operator=(right);
return *this;
}
Byte2& operator=(int i)
{
Byte::operator=(i);
return *this;
}
};
Thinking in C++ Page 6
Operator overloading & inheritance (example)
// Similar test function as in C12:ByteTest.cpp:
void k(Byte2& b1, Byte2& b2)
{
b1 = b1 * b2 + b2 % b1;
#define TRY2(OP) \
out << "b1 = "; b1.print(out); \
out << ", b2 = "; b2.print(out); \
out << "; b1 " #OP " b2 produces "; \
(b1 OP b2).print(out); \
out << endl;
b1 = 9; b2 = 47;
TRY2(+) TRY2(-) TRY2(*) TRY2(/)
TRY2(%) TRY2(^) TRY2(&) TRY2(|)
TRY2(<<) TRY2(>>) TRY2(+=) TRY2(-=)
TRY2(*=) TRY2(/=) TRY2(%=) TRY2(^=)
TRY2(&=) TRY2(|=) TRY2(>>=) TRY2(<<=)
TRY2(=) // Assignment operator
Thinking in C++ Page 7
Operator overloading & inheritance (example)
// Conditionals:
#define TRYC2(OP) \
out << "b1 = "; b1.print(out); \
out << ", b2 = "; b2.print(out); \
out << "; b1 " #OP " b2 produces "; \
out << (b1 OP b2); \
out << endl;
b1 = 9; b2 = 47;
TRYC2(<) TRYC2(>) TRYC2(==) TRYC2(!=) TRYC2(<=)
TRYC2(>=) TRYC2(&&) TRYC2(||)
// Chained assignment:
Byte2 b3 = 92;
b1 = b2 = b3;
}
Thinking in C++ Page 8
Multiple inheritance
• Multiple inheritance
Thinking in C++ Page 9
Multiple inheritance
• You can inherit from one class, so it would seem to make sense to inherit from more than one class at a time
• You shouldn’t try this until you’ve been programming quite a while and understand the language thoroughly
• Multiple inheritance seems simple enough
–However, multiple inheritance introduces a number of possibilities for ambiguity, which is why a chapter in Volume 2 is devoted to the subject
Thinking in C++ Page 10
Upcasting
• Upcasting
• Why “upcasting?”
• Upcasting and the copy constructor
• Pointer & reference upcasting
• A crisis
Thinking in C++ Page 11
Upcasting
• The most important aspect of inheritance
– the relationship expressed between the new class and the base class
–This relationship can be summarized by saying, “The new class is a type of the existing class”
Thinking in C++ Page 12
Upcasting (example)
//: C14:Instrument.cpp
// Inheritance & upcasting
enum note { middleC, Csharp, Cflat }; // Etc.
class Instrument {
public:
void play(note) const {}
};
// Wind objects are Instruments
// because they have the same interface:
class Wind : public Instrument {};
void tune(Instrument& i)
{
i.play(middleC);
}
int main()
{
Wind flute;
tune(flute); // Upcasting
} ///:~
Thinking in C++ Page 13
Why “upcasting?”
• Casting from derived to base moves up on the inheritance diagram, so it’s commonly referred to as upcasting
Thinking in C++ Page 14
Upcasting and the copy-constructor
• If you allow the compiler to synthesize a copy-constructor for a derived class, it will automatically call the base-class copy constructor, and then the copy-constructors for all the member objects
Thinking in C++ Page 15
Upcasting and the copy-constructor (example)
//: C14:CopyConstructor.cpp
// Correctly creating the copy-constructor
#include <iostream>
using namespace std;
class Parent {
int i;
public:
Parent(int ii) : i(ii)
{
cout << "Parent(int ii)\n";
}
Parent(const Parent& b) : i(b.i)
{
cout << "Parent(const Parent&)\n";
}
Parent() : i(0) { cout << "Parent()\n"; }
Thinking in C++ Page 16
Upcasting and the copy-constructor (example)
friend ostream& operator<<(ostream& os, const Parent& b)
{
return os << "Parent: " << b.i << endl;
}
};
class Member {
int i;
public:
Member(int ii) : i(ii)
{
cout << "Member(int ii)\n";
}
Member(const Member& m) : i(m.i)
{
cout << "Member(const Member&)\n";
}
Thinking in C++ Page 17
Upcasting and the copy-constructor (example)
friend ostream& operator<<(ostream& os, const Member& m)
{
return os << "Member: " << m.i << endl;
}
};
class Child : public Parent {
int i;
Member m;
public:
Child(int ii) : Parent(ii), i(ii), m(ii)
{
cout << "Child(int ii)\n";
}
friend ostream& operator<<(ostream& os, const Child& c)
{
return os << (Parent&)c << c.m << "Child: " << c.i << endl;
}
};
Thinking in C++ Page 18
Upcasting and the copy-constructor (example)
int main()
{
Child c(2);
cout << "calling copy-constructor: " << endl;
Child c2 = c; // Calls copy-constructor
cout << "values in c2:\n" << c2;
} ///:~
Thinking in C++ Page 19
Upcasting and the copy-constructor (example)
• Result
Parent(int ii)
Member(int ii)
Child(int ii)
calling copy-constructor:
Parent(const Parent&)
Member(const Member&)
values in c2:
Parent: 2
Member: 2
Child: 2
• If you try to write your own copy-constructor for Child then the default constructor will automatically be called for the base-class part of Child
• Child(const Child& c) : i(c.i), m(c.m) {}
Thinking in C++ Page 20
Upcasting and the copy-constructor (example)
• ResultParent(int ii)
Member(int ii)
Child(int ii)
calling copy-constructor:
Parent()
Member(const Member&)
values in c2:
Parent: 0
Member: 2
Child: 2
• If you try to write your own copy-constructor for Child then the default constructor will automatically be called for the base-class part of Child
• Child(const Child& c) : i(c.i), m(c.m) {}
Thinking in C++ Page 21
Pointer & reference upcasting
• upcasting
–occurs during the function call
– can also occur during a simple assignment to a pointer or reference
• ex)
–Wind w;
–Instrument* ip = &w; // Upcast
–Instrument& ir = w; // Upcast
Thinking in C++ Page 22
A crisis
• upcast loses type information about an object
–Wind w;
–Instrument* ip = &w;
� The compiler can deal with ip only as an Instrument pointer and nothing else
– It cannot know that ip actually happens to point to a Wind object