1、第三章 細部檢視類別3-1 指定物件3-2 傳遞物件給函數3-3 從函數中傳回物件3-4 簡介夥伴函數3-1 指定物件 物件之間的指定(assignment)運算nint x=5,y;ny=x;nmyclass ob1,ob2;nob1=ob2;/what happen?What happen?struct test int a,b;void main()test t1,t2;t1.a=10;t1.b=20;t2=t1;cout t2.a “t2.b endl;bit-wise copy(逐位元的複製)a 10b 20t1t2a 10b 20物件間的指定(assignment)#include
2、 using namespace std;class myclass int a,b;public:myclass()myclass(int x,int y)a=x;b=y;void show()cout a b;void main()myclass ob1(5,3),ob2;ob2=ob1;ob2.show();Q1:Output?Ans:bitwise copy for all data members Q2:這個程式有無bug?範例一:指定敘述是否需同一類型?class myclass int a,b;public:void show();void myclass:show()couta
3、bendl;class yourclass int a,b;public:void show();void yourclass:show()coutabendl;int main()myclass ob1;yourclass ob2;ob1=ob2;return 0;範例二:物件中有複合資料class stack int stk10;int tos;public:stack()tos=0;for(int i=0;i10;i+)stki=0;void push(int num)stktos=num;tos+;int pop()return stk-tos;void print()for(int
4、i=0;itos;i+)coutstkiendl;範例二:物件中有複合資料int main()stack s1,s2;s1.push(10);s1.push(20);s1.print();s2=s1;s2.print();return 0;範例三:如果物件中有指標class strtype char*p;int len;public:strtype()p=new char10;len=1;p0=0;strtype(char*s)p=new charstrlen(s)+1;len=strlen(s)+1;p=strcpy(p,s);strtype()delete p;void setChar(i
5、nt pos,char c)ppos=c;void show()coutlenendl;void main()strtype s1(“Hello”),s2;s2=s1;s2.setChar(1,x);s1.show();Q:以下程式會發生哪些問題?範例三:Problem 1p:0 x00f0cflen:5s1H e l l os2(1)執行 s2=s1;p:0 x00f0cflen:5(2)執行 s2.setChar(1,x)xWhats wrong?strtype s1(“Hello”),s2;範例三:Problem 2void main()strtype s1(“Hello”);strty
6、pe s2;s2=s1;p:0 x00f0cflen:5s1H e l l os2p:0 x00f0cflen:5s1,s2何時被消滅?物件消滅時會發生何事?解決方式void main()strtype s1(“Hello”);strtype s2;s2=s1;void main()strtype s1(“Hello”);strtype s2;s2.set(s1);p:0 x00f0cflen:5s1H e l l op 0 x00c800len:5s2H e l l onew!解決方式 請寫operator=class strtypestrtype&operator=(const strty
7、pe&s)p=new chars.len+1;strcpy(p,s.p);len=s.len;return*this;解決方式class strtype char*p;int len;public:strtype()p=new char10;len=1;p0=0;strtype(char*s)p=new charstrlen(s)+1;len=strlen(s)+1;p=strcpy(p,s);Q:以下程式會發生哪些問題?strtype()delete p;strtype&operator=(const strtype&s)p=new chars.len+1;strcpy(p,s.p);len
8、=s.len;return*this;void setChar(int pos,char c)ppos=c;void show()coutlenendl;解決方式void main()strtype s1(“Hello”),s2;s2=s1;s2.setChar(1,x);s1.show();3-2 傳遞物件給函數 回想從前:參數傳遞的方式void main()int x=5;fun1(x);fun2(&x);fun3(x);void fun1(int a)/call by?void fun2(int*p)/call by?void fun3(int&r)/call by?基礎:物件的生成與c
9、onstructorsclass samp int i;public:samp()i=0;samp(int n)i=n;samp(const samp&s)i=s.i;show()cout i endl;void main()samp ob1,ob2(3),ob3(ob2);範例一:1 class samp 2int i;3public:4samp(int n)i=n;5int get_i()return i;6 ;7 int sqr_it(samp o)return o.get_i()*o.get_i();8 void main()9samp a(10);10cout sqr_it(a)en
10、dl;11 cout a.get_i()endl;呼叫 sqr_it(a)後(1)生成物件 o(2)o將會以a為初值(3)同 samp o(a);會呼叫那一種constructor?沒有對應的constructor該如何?call-by-valuei:10i:10aosqr_it(a)sqr_it(samp o)Constructor vs.函數呼叫1 class samp 2int i;3public:4samp(int n)i=n;5samp(const samp&s)cout “copyn”;i=s.i;6int get_i()return i;7 ;8 int sqr_it(samp
11、o)return o.get_i()*o.get_i();9 void main()10samp a(10);11cout sqr_it(a)endl;12 呼叫時,哪一個建構子會被呼叫?(5)Copy constructorEX:哪一個constructor被呼叫?1 class samp 2int i;3public:4samp(int n)i=n;5samp(const samp&s)cout “copyn”;i=s.i;6int get_i()return i;7 ;8 int sqr_it(samp o)return o.get_i()*o.get_i();9 void main()
12、10samp a(10);11cout sqr_it(12)endl;12 呼叫時,哪一個建構子會被呼叫?(4)範例二:程式的輸出為何?class samp int i;public:samp(int n)i=n;void set(int n)i=n;int get_i()return i;void print()cout i;void sqrt_it(samp o)o.set(o.get_i()*o.get_i();void main()samp a(10);sqrt_it(a);a.print();範例三:程式的輸出為何?class samp int i;public:samp(int n
13、)i=n;void set(int n)i=n;int get_i()return i;void print()cout set(o-get_i()*o-get_i();void main()samp a(10);sqrt_it(&a);a.print();呼叫時,哪一個建構子會被呼叫?100指標之外,有無其他選擇?EX:call-by-reference呼叫時,哪一個建構子會被呼叫?100class samp int i;public:samp(int n)i=n;void set(int n)i=n;int get_i()return i;void print()cout i;void s
14、qrt_it(samp&o)o.set(o.get_i()*o.get_i();void main()samp a(10);sqrt_it(a);a.print();範例四:Copy Constructor 的重要性class strtype char*p;int len;public:strtype(char*s)p=new charstrlen(s)+1;strtype()delete p;void setChar(int pos,char c)ppos=c;void showMsg(strtype s)/*do something*/void main()strtype s1(“NTU
15、welcomes you!”);showMsg(s1);no copy constructor:bitwise copy結論如果class中的資料成員牽涉到動態記憶體配置,則以下成員函數不可省:ncopy constructornoperator=()或 set()儘量使用call-by-reference,why?nvoid showMsg(const strtype&str);nvoid showMsg(strtype str);3-3 從函數中傳回物件 回想從前void fun1()int fun2()double fun3()char*fun4()myclass fun5().範例一c
16、lass samp char s80;public:void show()cout s s;samp str;str.set(s);return str;void main()samp ob;ob=input();產生str產生暫時物件使用暫時物件設定obreturn str;返回mainob=input();呼叫input()暫時物件消滅下一道指令描述 當物件被函數傳回時會自動建立一個暫時物件(temporary object),內容即為回傳值(return value)。深入剖析物件的回傳class samp char s80;public:samp()cout“defaultn”;sam
17、p(const samp&ob)cout“copyn”;strcpy(s,ob.s);samp()cout “destroyn”;void show()cout s s;samp str;str.set(s);return str;(copy constructor)void main()samp ob;ob=input();ob.show();範例二:拜託你寫copy constructor好嗎?3-4 簡介夥伴函數(friend functions)什麼是夥伴函數?class myclass int n,d;public:myclass(int i,int j)n=i;d=j;bool i
18、sfactor(myclass ob)return!(ob.n%ob.d);void main()myclass ob(10,2);if(isfactor(ob)cout “2 是 10因數”;甚麼是夥伴函數?class myclass int n,d;public:myclass(int i,int j)n=i;d=j;friend bool isfactor(myclass ob);bool isfactor(myclass ob)return!(ob.n%ob.d);void main()myclass ob(10,2);if(isfactor(ob)cout “2 是 10因數”;夥伴
19、函數的用途 運算子超載(operator overloading)noperator+()noprrator()讓函數能存取二個多個不同類別的私用成員n破壞封裝.NOTE:class myclass int n,d;public:myclass(int i,int j)n=i;d=j;friend bool isfactor(myclass ob);bool isfactor(myclass ob)return!(ob.n%ob.d);void main()myclass ob(10,2);if(isfactor(ob)cout “2 是 10因數”;NOTE:夥伴函數不會被繼承一個函數可以是
20、多個類別的夥伴函數範例一:多個類別的夥伴class truck;/why this?class car int speed;public:car(int sp)speed=sp;friend int sp_greater(car c,truck t);class truck int speed;public:truck(int sp)speed=sp;friend int sp_greater(car c,truck t);int sp_greater(car c,truck t)return c.speed-t.speed;範例一:討論一定要如此嗎?破壞封裝精神main()car c(60)
21、;truck t(50);coutsp_greater(c,t)endl;範例二:將其他類別的成員函數做為夥伴函數class car;class truck int speed;public:truck(int sp)speed=sp;friend class car;class car int speed;public:car(int sp)speed=sp;int sp_greater(truck t)return speed-t.speed;main()car c(60);truck t(50);coutc.sp_greater(t)endl;範例三:friend 的有用之處#inclu
22、declass frac int q,p;public:frac(int n,int m)q=n;p=m;friend ostream&operator(ostream&out,const frac&ob);ostream&operator(ostream&out,const frac&ob)outob.q/ob.p;return out;void main()frac f(3,5);coutfendl;/f.print();NOTE:#include/using namespace std;class coordint x,y;public:coord()x=0;y=0;coord(int a,int b)x=a;y=b;friend ostream&operator(istream&stream,coord&ob);NOTE:ostream&operator(ostream&stream,coord&ob)streamob.x,ob.y(istream&stream,coord&ob)coutob.xob.y;return stream;int main()coord a(1,1),b(2,3);coutaa;couta;return 0;課後練習&綜合學習