C++ & OOP
description
Transcript of C++ & OOP
C++ & OOP
• Classes Syntax and Semantics• Object Model • Object Based Programming • Object Oriented Programming • Expertise
2002.07
J. J. Hou
J.J.Hou
田野調查
□ 曾經寫過程式□ 曾經寫過 C 程式□ 曾經寫過 C++ 程式□ 曾經寫過 C++ classes□ 曾經用過 C++ classes (例如 C++ 標準程式庫)
□ 曾經用過 Application Framework
J.J.Hou
本課程四個習題
□ class Fraction□ class String□ Shape hierarchy□ apply STL to your app.
J.J.Hou [email protected]
Bibliography
C++ 百科全書 C++ 標準程式庫百科全書
C++ 程式語言
經典本
專家經驗編程規範( coding standard)
C++ Supported Programming Paradigms
J.J.Hou [email protected]
•Procedural-based Programming•Abstract data type (ADT) Programming•Object-Oriented Programming•Generic Programming
C++ Standard Library : headers and “std”
J.J.Hou [email protected]
#include <string> // for string class#include <iostream> // for coutusing namespace std;
int main(){ string str1("Hello, World!"); cout << str1; // output: Hello, World!}
STL implementations•Microsoft VC6: P.J. Plauger•Inprise C++Builder4: Rogue Wave Software, Inc•GNU C++ egcs-2.91.57 : Silicon Graphics Computer Systems, Inc
STL components demo
J.J.Hou [email protected]
#include <algorithm>#include <functional>#include <vector>#include <iostream>
using namespace std;
int main(){ int ia[ 6 ] = { 27, 210, 12, 47, 109, 83 }; vector<int> vec( ia, ia+6 );
cout << count_if(vec.begin(), vec.end(), not1(bind2nd(less_equal<int>(), 40)));
return 0;}
#include <algorithm>#include <functional>#include <vector>#include <iostream>
using namespace std;
int main(){ int ia[ 6 ] = { 27, 210, 12, 47, 109, 83 }; vector<int> vec( ia, ia+6 );
cout << count_if(vec.begin(), vec.end(), not1(bind2nd(less_equal<int>(), 40)));
return 0;}
function adaptor(binder)
function object
container
generic algorithm
iterator
function adaptor(negator)
predicate
ref: C++ Primer 3/e p593
STL components
• containers (泛型容器)• In STL, containers are objects that store collections of other objects (STL, p23)• A sequence container holds an ordered collection of elements of a single type. such as vector, list (Primer p249)• An associative container supports efficient query as to the presence and retrieval of an element, such as map, set.
• generic algorithms (泛型演算法)• “algorithm” because they implement common operations such as min(), max(), find(), sort(); “generic” because they operate across multiple container types -- not only the vector and list types, but also the build-in array type.(Primer p571) • The container is bound to the generic algorithm operating on it by an iterator pair. (Primer p571)
• iterators (泛型指標)• An iterator provides a general method of successively accessing each element within any of the sequential or associative container types (Primer p265) . They generalize C/C++ pointers (STL p3).
• function objects• The traditional solution of parameterize the comparison operator is declaring a pointer to function. (Primer p587)• An alternative parameterization strategy to that of a pointer to function is a function object. A function object is a class that overloads the function call operator. (Primer p587)• which generalize ordinary C/C++ functions and allow other components to be efficiently adapted to a variety of tasks (STL p3)
• adaptors• A component that modifies the interface of another component (containers, iterators, function objects) (STL p40)
• allocators• for controlling storage management (STL p3). Every STL container class uses an allocator class to encapsulate information about the memory model the program is using (STL p43).
STL provides a set of C++ container classes and template algorithms designed to work together to produce a wide range of useful functionality.
declaration and definition in C++
J.J.Hou [email protected]
所謂宣告( declaration ),用來將一個 object 、 function 、 class 或 template 的型別名稱( type name )告訴編譯器。宣告式並不帶有細目資訊。下面統統都是宣告:
extern int x; // object declarationint numDigits(int number); // function declarationclass Clock; // class declaration
template<class T>class SmartPointer; // class template declaration
所謂定義( definition ),用來將細目資訊提供給編譯器。對 object 而言,定義式是編譯器為它配置記憶體的地點。對 function 或 function template 而言,定義式提供了函式本體( function body )。對 class 或 class template 而言,定義式必須列出該 class 或 template 的所有 members :
int x; // object definitionint numDigits(int number) // function definition{ ... }class Clock // class definition{ ... };
template<class T>class SmartPointer // class template definition{ ... };
Effective C++ Introduction
Class declaration and definition
J.J.Hou [email protected]
class CListItem; // forward declaration
class CList{ // ... CListItem* m_end; // 由於 m_end 是個指標,編譯器此時 CListItem* m_front; // 尚不需知道 CListItem 的細節。};
Class declaration and definition
J.J.Hou [email protected]
// complex,複數。根據數學定義,複數擁有實部 real 和虛部 imaginary。// 本例以 double 表現實部和虛部兩個值。class Complex // class head{public: Complex(const double& re=0, const double& im=0) : m_real(re), m_imag(im) // member initialization list { }
double real() const { return m_real; } double imag() const { return m_imag; }
double real(const double& re) { m_real = re; return m_real; } double imag(const double& im) { m_imag = im; return m_imag; }
private: double m_real; // real part(實部) double m_imag; // imaginary part(虛部)};
data members
member functions
Using Complex
J.J.Hou [email protected]
class Complex { … }; // maybe in header int main(){ Complex c1(1,2); Complex c2(3,4); Complex c3 = c1 * c2; Complex c4 = c1 + c2;
cout << c3 << endl; cout << c4 << endl; cout << c3.conj() << endl;}
name mangling and extern “C”
J.J.Hou [email protected]
class Complex{public: double real() const; double real(const double& re); // ...};
VC++ 編譯器為它們編出來的函式名稱 :
?real@Complex@@QBENXZ?real@Complex@@QAENABN@Z
•function signature•function prototype
可由 map file觀察獲得
private
J.J.Hou [email protected]
Q: 如果 member functions 接受同型的 object ,它有沒有權力直接存取該 object 的 private members ?
Complex& Complex::operator+=(const Complex& x){ m_real += x.m_real; // 直接取用參數 x 的 private m_real m_imag += x.m_imag; // 直接取用參數 x 的 private m_imag return *this;}
friend
J.J.Hou [email protected]
// in complex.hclass Complex{ friend ostream& operator<<(ostream& os, const Complex& r); ...}
// in complex.cppostream& operator<<(ostream& os, const Complex& x){ os << '(' << x.m_real // 直接取用 m_real << ',' << x.m_imag // 直接取用 m_imag << "i)"; return os;}
operator overloading : may be member or non-member
Scope and Lifetime
J.J.Hou [email protected]
•global(namespace)scope•local scope•file scope•namespace scope•class scope
•global object•local (auto) object•heap (dynamic allocated) object•static local object
寫一程式實地驗證 object lifetime (see the ctor’s and dtor’s invocation)
Big3
J.J.Hou [email protected]
Complex c1(); // default ctor? Function declaration!Complex c1; // default ctor
Complex c2(c1); // copy ctorComplex c3 = c1; // copy ctor
c3 = c1; // copy assignment operatorc3 = 2; // assignment operator
Complex* pc = new Complex(3,4); // heap objectdelete pc; // dtor
補充: Complex(); 是什麼?
Big3: ctor, dtor, operator=
J.J.Hou [email protected]
class Complex{public: explicit // default ctor, single-arguments ctor Complex(const double& re=0, const double& im=0) : m_real(re), m_imag(im) { } Complex(const Complex& x) // copy ctor : m_real(x.m_real), m_imag(x.m_imag) { } Complex& operator=(const Complex& x) // copy assignment operator { m_real = x.m_real; m_imag = x.m_imag; return *this; } ...};
Big3
J.J.Hou [email protected]
•編譯器自動合成 default ctor?•composition•inheritance•virtual mechanism
•編譯器自動合成 copy ctor•組合與繼承情況下的 copy 規則
•編譯器自動合成 copy assignment operator
特別注意 pointer member
Big3
J.J.Hou [email protected]
class Empty {public: Empty(); // default constructor Empty(const Empty& rhs); // copy constructor ~Empty(); // destructor — 見以下說明 // 以決定它是否為 virtual Empty& operator=(const Empty& rhs); // assignment operator Empty* operator&(); // address-of operators const Empty* operator&() const;};
class Empty {};Ref. Effective C++ 2e, p212
const Empty e1; // default constructor; // destructorEmpty e2(e1); // copy constructore2 = e1; // assignment operatorEmpty *pe2 = &e2; // address-of operator (non-const)const Empty *pe1 = &e1;// address-of operator (const)
pointers and references
J.J.Hou [email protected]
int x = 0;
int& r = x;
int* p = &x;
memory
r is a reference to x
p is a pointer to x
注意: sizeof(r) == sizeof(x)
int x=0;int* p = &x;int& r = x; // r 是一個 reference to int ,令它代表 x 。現在 r,x 都是 0
int x2=5;r = x2; // reference 不能重新代表其他物體。現在 r,x 都是 5
int* pi = 0; // null pointerint& ri = *pi; // ri 是一個 null reference 嗎?
Ref. More Effective C++, p10
by value v.s. by reference.
J.J.Hou [email protected]
Complex& Complex::operator+=(const Complex& x){ m_real += x.real(); // m_real += x.m_real; // 可直接取用參數 x 的 private m_real this->m_imag += x.imag(); // 有沒有 this-> 都一樣 return *this;}
Complex conj(const Complex& x) // 共軛複數{ return Complex(x.real(), -x.imag()); // impel RVO. // i.e. // Complex c(x.real(), -x.imag()); // return c; // local object, so must return by value}
Ref. Effective C++, p96 : in the class C, ‘this’ like below: C* const this; // for non-const member functionconst C* const this; // for const member function
本例既然直接修改了 *this. 是否可以將回傳值設為 void ? Try it!
This Pointer (Hidden)
J.J.Hou [email protected]
classdefinition
object 2object 2object 1object 1 object 3object 3 object 4object 4 object 5object 5
instantiation
member functions implementation code
member functions implementation code
data members
serve
根據不同的 this 指標,指向不同的 objects 實體
object size
ref: Polymorphism in C++ p37 chap1
object size
(in somewhere)
Secrets of “this” pointer
J.J.Hou [email protected]
Complex& Complex::operator+=(Complex* this, const Complex& x){ this->m_real += x.m_real; this->m_imag += x.imag(); return *this;}
Complex c1(2,3);Complex c2(3,4);cout << c1 += c2;
cout << c1.operator+=(c2);
operator<<(cout, c1.operator+=(c2));
operator<<(cout, Complex::operator+=(&c1, c2));
Secrets of “this” pointer
J.J.Hou [email protected]
Complex c1(2,3);Complex c2(3,4);cout << c1 += c2;cout << c2 += c1;
C1
C2
Complex& Complex::operator+=(Complex* this, const Complex& x){ ... }
by value v.s. by reference. tips
J.J.Hou [email protected]
o. 儘量使用 by reference ,不要使用 by valueo. 不要在函式中傳回 reference to local object (會造成 dangling )o. 不要在函式中傳回 pointer to heap object (會造成 memory leak )o. 不要傳出 data members 的任何權柄( handle )o. 如果一定得 by value ,不必拼命嘗試 by reference 例如 Complex Complex::conj(const Complex& x); 或如 Rational Rational::operator*(const Rational& x);
Constness
J.J.Hou [email protected]
const 用來修飾 member functions ,可以使編譯器協助我們測定 const objects 和 member functions 之間的互動關係是否合法
const object (data members 不可有任何變動 )
non-const object (data members 可有變動 )
const member function ( 保證不更改 data members)
non-const member function ( 不保證 data members 不變 )
const String(“hello world”);String.print();// 如果當初設計 string::print() 時未指明 const ,以上便是經由 const object 喚起 non-const member function ,會出錯。
new operator and operator new
J.J.Hou [email protected]
Complex* pc = new Complex(1,2);
Complex *pc;try { void* mem = ::operator new( sizeof(Complex) ); // 配置記憶體 pc = static_cast<Complex*>(mem); // 轉型 pc->Complex::Complex(1,2); // 建構 // 注意:只有編譯器才可以像上面那樣直接呼叫 ctor}catch( std::bad_alloc ) { // operator new 配置記憶體失敗,不執行 constructor。}
欲直接喚起 ctor, 可利用 placement new : new(p) Complex(1,2);
編譯器轉為 ...
J.J.Hou [email protected]
delete operator and operator delete
pc->~Complex(); // 先解構::operator delete(pc); // 然後釋放記憶體
Complex* pc = new Complex(1,2);...delete pc;
編譯器轉為 ...
array new and array delete
J.J.Hou [email protected]
Complex* pca = new Complex[3];...delete[] pca;
Complex objectpa
cookie, 記錄記憶體大小
Complex object
Complex object
喚起三次 ctor, 但無法給予初值
喚起三次 dtor
inline function. (test)
J.J.Hou [email protected]
inline void func(){ int i, j;}
int main(){ int i, j; func(); return 0;}
inlining
inline function 有 macro 的優點而無其缺點
auto_ptr (1)
J.J.Hou [email protected]
template<class T>class autoPtr{public: // construct/copy/destroy explicit autoPtr(T* p=0) // default ctor : m_ptr(p) { }
autoPtr(autoPtr& a) // copy ctor : m_ptr( const_cast<autoPtr&>(a).release() ) { }
autoPtr& operator=(autoPtr& rhs) { reset(rhs.release()); return *this; }
~autoPtr() { delete m_ptr; }
auto_ptr (2)
J.J.Hou [email protected]
T& operator*() const { return *m_ptr; } T* operator->() const { return m_ptr; } T* get() const { return m_ptr; } T* release() { // 釋放擁有權並傳回被擁有物的位址 T* tmp = m_ptr; m_ptr = 0; return tmp; } void reset(T* p = 0) { // 刪除原先擁有物,重設為擁有 p if (m_ptr != p) { delete m_ptr; m_ptr = p; } }
private: T* m_ptr; // dump pointer};
auto_ptr , return a pointer to heap object
J.J.Hou [email protected]
{Complex* pc = func3(2, 3); // pc 接獲 a pointer to heap object.cout << *pc << endl; // (2,3i)//delete pc; // 本應 delete。但後面使用 auto_ptr...auto_ptr<Complex> pc_auto; // GCC not support auto_ptr.pc_auto.reset(pc); // VC6 not support reset().cout << *pc_auto << endl; // (2,3i)
// auto_ptr<Complex> pc_auto2 = func3(3,4); // bcb4 errorauto_ptr<Complex> pc_auto2(func3(3,4)); // ok in bcb4 and vc6cout << *pc_auto2 << endl; // (3,4i)}
Complex* func3(double d1, double d2){ Complex* pc = new Complex(d1,d2); // heap object // ... return pc; // return a pointer to heap object}
Polymorphism in STL
J.J.Hou [email protected]
list<CShape*> m_myList
list<CShape*> m_myList
list<CShape*>::push_back()可以把一個 CShape* 放入 list 尾端
CMyDoc
iterator
ref: Polymorphism in C++ p79 chap1
CCircleCCircle
CTriangleCTriangle
CEllipseCEllipse
CSquareCSquare
CRectCRect
CShapeCShape
Inheritance and SubObjects
J.J.Hou [email protected]
CPoint3dobject
CPoint3dobject
CPoint2dsubobject
CPointsubobject
12bytes
8bytes
4bytes
CPointmember functions
CPointmember functions
CPoint2dmember functions
CPoint2dmember functions
CPoint3dmember functions
CPoint3dmember functions
處理 CPoint subobject
處理 CPoint2d subobject(涵蓋 CPoint subobject )
處理 CPoint3d object(涵蓋 CPoint2d subobject
和 CPoint subobject )
ref: Polymorphism in C++ p47 chap1
C++ Object Model : Object Layout for Single Inheritance
J.J.Hou [email protected]
ref: Polymorphism in C++ p104 fig2-2
vptr
ClassA::m_data1
m_data2
m_data3
m_data1
m_data4
vptr
m_data1
m_data2
m_data3
vptr
m_data1
m_data2
a (ClassA object)
b (ClassB object)
c (ClassC object)
12bytes
16bytes
24bytes
ClassA::m_data1
m_data2
m_data3
m_data1
m_data4
m_data1
m_data2
m_data3
m_data1
m_data2
a (ClassA object)
b (ClassB object)
c (ClassC object)
8bytes
12bytes
20bytes
ClassAsubobject
ClassBsubobject
ClassAsubobject
ClassBsubobject
class A,B,C with
virtual function(s)
class A,B,C without virtual
function(s)
B
C
A
0x4090240x0063FDC4
ClassA::m_data10x0063FDC8
m_data20x0063FDCC
m_data30x0063FDD0
m_data10x0063FDD4
m_data40x0063FDD8
vptr
0x4090140x0063FDDC
m_data10x0063FDE0
m_data20x0063FDE4
m_data30x0063FDE8
vptr0x401F80
0x401F10
0x409004
m_data1
m_data2
vptr0x401ED0
0x401F10
ClassA’s vtbl
0x401FF0
0x401F10
ClassA::func1()
ClassA::func2()
a (ClassA object)
b (ClassB object)
c (ClassC object)
0x0063FDEC
0x0063FDF0
0x0063FDF4
0x00409004
0x00409014
0x00409024
0x00409008
0x00409018
0x00409028
00x0040900C
00x0040901C
00x0040902C
ClassA::vfunc1()
ClassA::vfunc2()
ClassB::func2()
ClassB::vfunc1()
ClassC::vfunc1()
ClassC::func2()
functions implementation
ClassB’s vtbl
ClassC’s vtbl
ref: Polymorphism in C++ p105 fig2-3
C++ Object Model :vptr and vtbl
C++ Object Model : one polymorphic class, one vtbl
J.J.Hou [email protected]
ref: Polymorphism in C++ p108 fig2-4
0x4090140x0063FDA0
m_data1
m_data2
vptra2 (ClassA object)
0x00409014
ClassA’s vtbl
0x4090140x0063FD70
m_data1
m_data2
vptra1 (ClassA object)
0x4090140x0063FD8C
m_data1
m_data2
vptr
a3 (ClassA object)
J.J.Hou [email protected]
Inheritance vs. Composition
Public inheritance models “is-a”
private inheritance models “is implemented-in-terms-of”
composition models “has-a”
Liskov substitution principle : an object of a derived class should be usable wherever an object of its public base class is.