580 likes | 842 Views
程序设计实习 第二十一讲 习题课. 类和对象基本概念 (1). 写出下面程序的运行结果 class Apple { private : static int nTotalNumber; public: Apple() { nTotalNumber ++; } ~Apple( ) { nTotalNumber --; } static void PrintTotal() { cout << nTotalNumber << endl; } }; int Apple::nTotalNumber = 0;
E N D
类和对象基本概念(1) 写出下面程序的运行结果 class Apple { private : static int nTotalNumber; public: Apple() { nTotalNumber ++; } ~Apple( ) { nTotalNumber --; } static void PrintTotal() { cout << nTotalNumber << endl; } }; int Apple::nTotalNumber = 0; Apple Fun( const Apple & a ) { a.PrintTotal(); return a ; } int main () { Apple * p = new Apple[4]; Fun( p[2]); Apple p1, p2; delete [] p; p1.PrintTotal(); } 解析:return返回时,产生临时变量,Total Number析构时会减小 4 1
类和对象基本概念(2) *写出下面程序的运行结果 class Sample{ public: int v; Sample() { }; Sample(int n):v(n) { }; Sample( Sample & x) { v = 2 + x.v ; } }; Sample PrintAndDouble( Sample o){ cout << o.v <<endl; o.v = 2 * o.v; return o; } int main(){ Sample a(5); Sample b = a; Sample c = PrintAndDouble( b ); cout << c.v << endl; Sample d; d = a; cout << d.v ; } 解析:构造函数和复制构造函数的调用 9 22 5 注意区分: Sample b=a; d=a; (vc2008实际运行结果为20)
类和对象基本概念(3) 程序输出结果如下,请填空 0 5 class A { public: int val; A(____________ ){ val = n; }; ___________ GetObj() { return ________; } }; main() { A a; cout <<a.val << endl; a.GetObj() = 5; cout << a.val << endl; } A(int n=0) A& GetObj(){ return *this; } 或者 int& GetObj(){ return val; }
类和对象基本概念(4) 程序输出结果如下,请填空 3+4i 5+6i 补足Complex类的成员函数,不能增加成员变量 class Complex { private: double r,i; public: void Print() {cout << r << "+" << i << "i" << endl;} }; int main() { Complex a; a = "3+4i"; a.Print(); a = "5+6i"; a.Print(); }
类和对象基本概念(4) 构造函数 Complex() {}; Complex (const char t[]) { if(!t) { r=0.0; i=0.0; } else { r = t[0] - '0'; i = t[2] - '0'; } } • 另一种思路 重载赋值操作符 Complex &operator=(const char t[]) { if(!t) { r=0.0; i=0.0; } else { r = t[0] - '0'; i = t[2] - '0'; } return *this; }
类和对象基本概念(5) 程序输出结果如下,请填空 10 补足Sample类的成员函数,不能增加成员变量 class Sample{ public: int v; Sample(int n):v(n) { }; }; main() { Sample a(5); Sample b = a; cout << b.v ; } Sample( Sample & x) { v = 2 * x.v ; }
类和对象基本概念(6) 程序输出结果如下,请填空 This Hello 补足MyString类的成员函数,不能增加成员变量 class MyString{ char * p; public: MyString( char * s ) { p = new char[strlen(s)+1]; strcpy(p,s); } ~MyString() { delete [] p;} const char * c_str() { return p;} }; • main(){ • MyString s1("This"), s2 =s1; • s2.Copy ( "Hello"); • cout << s1.c_str () • << endl << s2.c_str () ; • }
类和对象基本概念(6) 补足成员函数 void Copy( char * s) { delete [] p; p = new char[strlen(s)+1]; strcpy(p,s); } MyString( MyString & o ) { p = new char[strlen(o.p ) + 1 ]; strcpy( p, o.p); }
类和对象基本概念(7) 程序输出结果如下,请填空 5,5 5,5 class Base { public: int k; Base (int n) : k(n) { } }; class Big{ public: int v; Base b; Big _____________ { } Big _____________ { } }; Big(int n):v(n),b(n){ } Big(Big & x):v(x.v),b(x.b.k){ } • main(){ • Big a1(5); • Big a2 = a1; • cout << a1.v << "," • << a1.b.k << endl; • cout << a2.v << "," • << a2.b.k << endl; • }
运算符重载(1) 程序输出结果如下,请填空 4,1 请写出被隐藏的部分,MyInt的成员函数里不允许使用静态变量 class MyInt { int nVal; public: MyInt( int n) { nVal = n ;} int ReturnVal() { return nVal;} …………………. }; main () { MyInt objInt(10); objInt-2-1-3; cout << objInt.ReturnVal(); cout <<","; objInt-2-1; cout << objInt.ReturnVal(); } MyInt & operator -( int x) { nVal -= x; return * this; }
运算符重载(2) *程序输出结果如下,请填空 (4,5) (7,8) class Point { private: int x; int y; public: Point(int x_,int y_ ):x(x_),y(y_) { }; _____; }; _____ operator << (_____, const Point & p) { _____; return ______; } main(){ cout << Point(4,5) << Point(7,8); }
运算符重载(2) class Point { private: int x; int y; public: Point(int x_,int y_ ):x(x_),y(y_) { }; _____; }; _____ operator << (_____, const Point & p) { _____; return ______; } friend ostream & operator<< ( ostream & o, const Point & p); ostream & operator << ( ostream & o, const Point & p) o << "(" << p.x << "," << p.y << ")"<< endl; o
运算符重载(3) *程序输出结果如下,写一个二维数组类 Array2 0,1,2,3, 4,5,6,7, 8,9,10,11 next 0,1,2,3, 4,5,6,7, 8,9,10,11
运算符重载(3) using std::cout; using std::endl; int main(){ Array2 a(3,4); int i,j; for( i = 0;i < 3; i ++ ) for( j = 0; j < 4; j ++ ) a[i][j] = i * 4 + j; for( i = 0;i < 3; i ++ ) { for( j = 0; j < 4; j ++ ) { cout << a(i,j) << ","; } cout << endl; } cout << "next" << endl; Array2 b; b = a; for( i = 0;i < 3; i ++ ) { for( j = 0; j < 4; j ++ ) { cout << b[i][j] << ","; } cout << endl; } return 0; }
运算符重载(3) class Array2 { private: int * p; int r,c; public: Array2() { p = NULL ; } Array2( int r_, int c_ ):r(r_),c(c_) { p = new int [ r * c]; } Array2( Array2 & a ):r(a.r),c(a.c) { p = new int [r * c]; memcpy( p, a.p, sizeof(int )*r*c); } Array2 & operator=(const Array2 & a) { if( p ) delete [] p; r = a.r; c = a.c;p = new int [r * c]; memcpy( p, a.p, sizeof(int ) * r * c); return * this; } ~Array2() { if( p) delete [] p; } int * operator [] ( int i ) { return p + i * c; } int & operator() ( int i,int j ) { return p[ i * c + j]; } 注:重载的实际上是第二维的[],第一维的[]直接调用int型一维数组的定义
运算符重载(3):第二种解法 class CWordArr{ private: int *m_pdat; long m_size; public: CWordArr(long size) { m_pdat= new int[size]; m_size = size; }; ~CWordArr() { delete[] m_pdat; }; int& operator[](long idx) { return m_pdat[idx]; } };
运算符重载(3):第二种解法 • ~ Array2() { • for (long i=0;i<m_col;i++) { • delete m_p[i]; • m_p[i]=NULL; • } • delete[] m_p; • } • CWordArr& operator[](long idx) { • return *m_p[idx]; • } • int & operator() ( int i,int j ) { • return (*m_p[i])[j]; • }} class Array2{ private: CWordArr **m_p; long m_col,m_row; public: Array2(long col,long row) { m_p=new CWordArr*[col]; for (long i=0;i<col;i++) m_p[i]= new CWordArr(row); m_col=col; m_row=row; } • 通过两次[]重载的叠加,就可以用a[x][y]的方式来访问数组元素 • C++不可能在一个类里面实现[][]的重载(若这种相当于三元算符),因此有两个类:一个是一维数组类,实现[]的重载;另一个类是二维数组类,必须持有一组一维数组类的实例,存放二维数组的各个行的数组,二维数组类也要重载[]运算符
运算符重载(4) 程序输出结果如下,写一个HugeInt类 1)100000089000000 2)100000089000000 3)10000 4)10000 5)10001 6)10006 7)100000089010006
运算符重载(4) void main(){ CHugeInt a("1234545436342424354354365289899834234235"); CHugeInt d(9999); CHugeInt temp = CHugeInt("100000088888888") + 111112; CHugeInt temp2 = 111112+CHugeInt("100000088888888"); cout << "1)" << temp << endl; cout << "2)" << temp2 << endl; cout << "3)" << ++d << endl; cout << "4)" << d++ << endl; cout << "5)" << d << endl; d += 5; cout << "6)" << d << endl; cout << "7)" << d + temp; }
运算符重载(4) //重载运算符+ CHugeInt operator +(const CHugeInt & n) const { CHugeInt tmp( * this); for( int i = 0;i < MAX ; i ++ ) { tmp.Number[i] += n.Number[i];//逐位相加if( tmp.Number[i] >= 10 ) {//看是否要进位 tmp.Number[i] -= 10; tmp.Number[i+1] ++;//进位 } } return tmp; } const CHugeInt & operator++() { * this = ( * this ) + 1; return * this; }// ++n const CHugeInt operator++(int n) { CHugeInt tmp = * this; * this = ( * this ) + 1; return tmp; }//n++ const CHugeInt operator +=( const CHugeInt & n){ * this = ( * this ) + n; return * this; } 代码过多,只截取部分
运算符重载(4) friend ostream & operator << (ostream & o, const CHugeInt & n); friend CHugeInt operator+ ( int n1 , const CHugeInt & n2); CHugeInt operator + ( int n1 ,const CHugeInt & n2) { return n2 + n1; } ostream & operator << ( ostream & o, const CHugeInt & n){ bool bStart = false; for( int i = MAX -1; i >= 0 ; i -- ) { if( n.Number[i] ) { bStart = true; } if( bStart ) cout << n.Number[i]; } if( !bStart )//没有数字时,输出0 cout << 0; return o; }
继承和多态(1) 程序输出结果如下,写一个Mystring类 1. abcd-efgh-abcd-2. abcd-3.4. abcd-efgh-5. efgh-6. c7. abcd-8. ijAl-9. ijAl-mnop10. qrst-abcd-11. abcd-qrst-abcd- uvw xyz aboutbigmetakeabcdqrst-abcd-
Mystring类(1) #include<iostream> #include<cstring> using namespace std; class MyString { public: char *p; MyString() // 构造函数 { p = NULL; } MyString(char *t) // 构造函数 { p = new char[strlen(t) + 1]; strcpy(p,t); } MyString(const MyString &s) // 复制构造函数 { p = new char[strlen(s.p) + 1]; strcpy(p, s.p); }
Mystring类(2) ~MyString() // 析构函数 { if(p) delete[]p; } MyString operator+(const MyString &s) // +号重载,这里表示 //两个MyString类型相加的情况 { char *q; q = new char[strlen(p) + strlen(s.p)+1]; strcpy(q, p); strcat(q, s.p); MyString temp(q); delete []q; return temp; }
Mystring类(3) MyString operator+(const char *s) // +号重载,这里表示 //MyString类型+字符串的情形 { char *q; q = new char[strlen(p) + strlen(s) + 1]; strcpy(q, p); strcat(q, s); MyString temp(q); delete []q; return temp; } MyString& operator=(const MyString &s) // 赋值号重载 { if(p!=NULL) { delete[]p; } p = new char[strlen(s.p)+1]; strcpy(p, s.p); return *this; }0
Mystring类(4) char &operator[](int n) // []号重载 { return p[n]; } MyString& operator+=(char *s) // +=号重载 { char *q; q = new char[strlen(p)+1]; strcpy(q, p); if(p != NULL) { delete []p; } p = new char[strlen(p) + strlen(s) + 1]; strcpy(p,q); strcat(p,s); delete []q; return *this; }
Mystring类(5) MyString operator()(int i, int n) { // ()重载 char *q; q = new char[n+1]; strncpy(q, p+i, n); q[n] = '\0'; MyString temp(q); delete []q; return temp; } }; ostream &operator<< (ostream &o, const MyString &s) // <<号重载 { o << s.p; return o; } MyString operator+(char *s, const MyString &t) // +号重载,这里是字符串+MyString的情形 { char q[100]; strcpy(q, s); strcat(q, t.p); return MyString(q); }
Mystring类(6) // <,==,> 号的重载 int operator<(const MyString &s1, const MyString &s2) { if(strcmp(s1.p,s2.p) < 0) { return 1; } else { return 0; } } int operator==(const MyString &s1, const MyString &s2) { if(!strcmp(s1.p, s2.p)) { return 1; } else { return 0; } } int operator>(const MyString &s1, const MyString &s2) { if(strcmp(s1.p, s2.p) > 0) { return 1; } else { return 0; } }
Mystring类(8) 从string类派生的写法 class MyString : public string{ public: MyString():string() {}; MyString( const char * s):string(s){}; MyString( const string & s ): string(s){}; MyString operator() ( int s, int l) { return this->substr(s,l); }; };
继承和多态(2) 写出下面程序的运行结果 class D:public B { private : int nDVal; public: void Print() { B::Print(); cout << "nDVal="<<nDVal <<endl; } D( int n) : B(3*n) {nDVal = n;} void Fun() { cout << "D::Fun" << endl; } }; class B { private: int nBVal; public: void Print() { cout << "nBVal="<< nBVal << endl; } void Fun() {cout << "B::Fun" << endl; } B ( int n ) { nBVal = n;} };
继承和多态(2) main() { B * pb; D * pd; D d(4); d.Fun(); pb = new B(2); pd = new D(8); pb -> Fun(); pd->Fun(); pb->Print (); pd->Print (); pb = & d; pb->Fun(); pb->Print(); } D::Fun B::Fun D::Fun nBVal=2 nBVal=24 nDVal=8 B::Fun nBVal=12
继承和多态(3) 程序输出结果如下,请填空 A::Fun A::Do A::Fun C::Do class B:public A { public: virtual void Do() { cout << "B::Do" << endl;} }; class C:public B { public: void Do( ) { cout <<"C::Do"<<endl; } void Fun() { cout << "C::Fun" << endl; } }; class A { private: int nVal; public: void Fun() { cout << "A::Fun" << endl; }; virtual void Do() { cout << "A::Do" << endl; } };
继承和多态(3) void Call(____________) { p->Fun(); p->Do(); } main() { Call( new A()); Call( new C()); } A & p A * p void Call(____________) { p.Fun(); p.Do(); } main() { Call(A()); Call(C()); }
模板(1) *设计CLinkList类模板中AppendNode 和PrintList成员函数,得到如下结果 0,1,2,3, 0,1,2,3,9,10,11, 注意: 1)不得调用任何库函数,库模板,不得使用static关键字,不得使用除 NULL 以外的任何常量 2)不得为Node和CLinkList模板添加任何成员 3)不得添加任何全局变量,不得添加其他函数
模板(1) template <class D> class Node { public: D data; Node * next; }; template<class D> class CLinkList { private: Node<D> * pHead; public: CLinkList(); void AppendNode( D data); void PrintList(); }; template<class D> CLinkList<D>::CLinkList() { pHead = new Node<D>; pHead->next = NULL; }; main() { CLinkList<int> l; for( int i = 0;i < 4;i ++) l.AppendNode(i); l.PrintList(); cout << endl; for( i = 9;i < 12;i ++) l.AppendNode(i); l.PrintList(); }
模板(1) template<class D> void CLinkList<D>::AppendNode( D data) { Node<D> * p = pHead; while( p->next ) p = p->next; p->next = new Node<D>; p = p->next; p->data = data; p->next = NULL; } template<class D> void CLinkList<D>::PrintList() { Node<D> * p = pHead; while( p->next ) { cout << p->next->data << ","; p = p->next; } }
模板(2) 填空使程序能编译通过,并写出运行的输出结果 #include <iostream> template <_____________> class myclass { T i; public: myclass (T a) { i = a; } void show( ) { cout << i << endl; } }; void main() { myclass<________> obj("This"); obj.show(); } class T This 该程序输出结果为:_____ char *
模板(2) 填空得到以下结果 TomHanks 注意,不允许使用任何常量 ~myclass( ) { delete [] p; } void Show() { for( int i = 0;i < nSize;i ++ ) { cout << p[i]; } } }; main() { char * szName = "TomHanks"; myclass<char > obj (____________________); obj.Show(); } template <class T> class myclass { _________; int nSize; public: myclass ( ______________, int n) { p = new T[n]; for( int i = 0;i < n;i ++ ) p[i] = a[i]; nSize = n; } T * p T * a szName,strlen(szName)
STL(1) 看程序写结果 main() { vector<A*> vp; vp.push_back(new A(1)); vp.push_back(new A(2)); vector<A> v; v.push_back (3); } class A { private : int nId; public: A(int n) { nId = n; cout << nId << " contructor" << endl; }; A( const A & a ) { nId = a.nId ; cout << nId << " copy constructor" << endl; } ~A( ) { cout << nId << " destructor" << endl; } }; 1 contructor 2 contructor 3 contructor 3 copy constructor 3 destructor 3 destructor
STL(2) 程序输出结果如下,请填空 Tom,Jack,Mary,John, template <_______ , _______> class MyClass { T array[T2]; public: MyClass( T * begin ) { copy( begin, begin + T2, array); } void List() { T * i; for( i = array; i != array + T2;i ++) cout << * i << "," ; } }; class T int T2 main() { string array[4] = { "Tom","Jack","Mary","John"}; _____________________ ; obj.List(); } MyClass<string,4> obj(array)
STL(3) 程序输出结果如下,请填空 Tom,Jack,Mary,John, main() { string array[4] = { "Tom","Jack","Mary","John"}; _________________________; obj.List(); } template <class T> class MyClass { vector<T> array; public: MyClass ( T * begin,int n ):array(n) { copy( begin, begin + n, array.begin()); } void List() { ________________________; for( i = array.begin(); i != array.end();i ++) cout << * i << "," ; } }; MyClass<string> obj( array,4) vector<T>::iterator i;
STL(4) 程序输出结果如下,请填空 1 2 6 7 8 9 main() { int a[] = {8,7,8,9,6,2,1}; ___________________; for( int i = 0;i < 7;i ++ ) ___________________; ostream_iterator<int> o(cout," "); copy( v.begin(),v.end(),o); } set<int >v v.insert(a[i])
STL(5) 程序输出结果如下,请填空 A::Print: 1 B::Print: 2 B::Print: 3 template <class T> void PrintAll( const T & c ){ T::const_iterator i; for( i = c.begin(); i != c.end(); i ++ ) _______________________; }; class A { protected: int nVal; public: A(int i):nVal(i) { } virtual void Print() { cout << "A::Print: " << nVal << endl; } }; (*i)->Print()
STL(5) class B:public A { public: B(int i):A(i) { } void Print() { cout << "B::Print: " << nVal << endl; } }; main() { __________________; v.push_back( new A(1)); v.push_back (new B(2)); v.push_back (new B(3)); PrintAll( v); } vector<A*> v
STL(6) *写一个自己的 CMyostream_iterator 模板,使之能和 ostream_iterator 模板达到一样的效果 using namespace std; main() { int a[5] = {1,2,3,4,5}; CMyostream_iterator<int> output(cout,"*"); vector<int> v(a,a+5); copy(v.begin(),v.end(),output); }
提示 要支持copy函数必须重载三个运算符:*,=,++ 参考 copy 的help template<class InIt, class OutIt> OutIt copy(InIt first, InIt last, OutIt x); The template function evaluates *(x + N) = *(first + N)) once for each N in the range [0, last - first), for strictly increasing values of N beginning with the lowest value. It then returns x + N. If x and first designate regions of storage, x must not be in the range [first, last) copy 的源代码: template<class _II, class _OI> inline _OI copy(_II _F, _II _L, _OI _X) {for (; _F != _L; ++_X, ++_F) *_X = *_F; return (_X); } 47
STL(6) template <class T> class CMyostream_iterator { private: ostream & o; string s; public: CMyostream_iterator( ostream & output, const char * sz): o(output),s(sz) {} void operator++() { }; void operator=(const T & val ) { o << val << s; } CMyostream_iterator & operator * ( ) { return * this; } };
STL(7) 程序输出结果如下,请填空 5*3*4*2*1* 1*2*3*4*5* 1*2*9*4*5* main() { MyClass<int> obj(5); int a[] = { 5, 3, 4, 2,1 }; copy( a, a + 5, obj.begin()); ostream_iterator<int> output (cout,"*"); copy( obj.begin(),obj.end(),output); cout << endl; obj.sort(); copy( obj.begin(),obj.end(),output); cout << endl; obj[2] = 9; copy( obj.begin(),obj.end(),output); } template <class T> class MyClass: public list<T> { public: ____________________ (int n) { iterator i; int k = 0; for( ____________________________) { if( k == n) return _______________; k ++; } } MyClass(int n):___________________ {} }; T& operator[] i=begin();i != end(); i ++ * i list<T>(n) 注意:list容器类派生类的初始化
STL(8) 标准矩形问题 其边平行于坐标轴 给定不重复的 n 个整点(横、纵坐标都是整数的点),求从这n个点中任取4点作为顶点所构成的四边形中,有多少个是标准矩形。 输入数据: 第一行是点的数目 其后每一行都代表一个点,由两个整数表示,第一个是x坐标,第二个是y坐标 输出要求: 输出标准矩形的数目