C++随笔(四)
1.成员函数的定义
两种形式:一种是在类声明中只给出成员函数的原型,函数体在类的外部定义。
void point::setposit(int a, int y)
{ x=a; y=b;}
int point::getx( )
{ return x; }
int point::gety( )
{ return y; }
另一种是内置函数:将成员函数定义在类内部,即内置函数,(一种是直接将函数定义在内部,将函数放在类定义体外,在函数定义体之前冠以“inline”,起到内置函数的作用。)
class point { private: int x, y; public: void Setposit(int, int); int getx( ); int gety( ); }; inline void point::setposit(int a, int y) { x=a; y=b; } inline int point::getx( ) { return x; } inline int point::gety( ) { return y; }
2.拷贝构造函数
拷贝构造函数是一种特殊的构造函数。用于依据已存在的对象建立一个新对象。
用户可以根据需要定义拷贝构造函数
系统也可以为类产生一个缺省的拷贝构造函数
#include <iostream.h> class point { int x,y; public: point(int a,int b) { x=a; y=b; } void print() { cout<<x<<" "<<y<<endl;} }; int main() { point p1(30, 40); point p2(p1); point p3=p1; p1.print(); p2.print(); p3.print(); int x; cin >> x; return 0; }
3.对象数组
若类中含有用户定义的构造函数,而且构造函数带有参数,则定义对象数组时,可通过初始值表进行赋值,例如3-13。
若类中含有构造函数,则定义对象数组时,可通过不带参数的构造函数或带有缺省参数的构造函数给对象数组赋值,例如3-14。
#include <iostream.h> class exam { public: int x; public: exam(int n) { x=n; } int get_x() { return x; } }; int main() { exam ob[4]={11,22,33,44}; for(int i=0; i<4; i++) cout<<ob[i].get_x()<<' '; cout <<endl; return 0; }
#include <iostream.h> class point { private: int x,y; public: point() { x=5; y=5; } point(int a,int b) { x=a; y=b; } int getx() { return x; } int gety() { return y; } }; int main() { point op(3, 4); cout<<"op x="<<op.getx()<<endl; cout<<"op y="<<op.gety()<<endl; point op_array[20]; cout<<"op_array[1] x="<<op_array[1].getx()<<endl; cout<<"op_array[1] y="<<op_array[1].gety()<<endl; int x; cin >> x; return 0; }
4.参数传递:
向函数传递对象时,通过传值调用传递给函数,即把对象的拷贝而不是对象本身传递给函数,函数中对对象的修改不影响调用该函数的对象本身。
也可以将对象的地址传递给函数。这时函数对对象的修改将影响调用该函数的对象本身。
观察例子进行比较
值不变
#include <iostream.h> class tr { int i; public: tr(int n) {i=n;} void set_i(int n) {i=n;} int get_i() {return i;} }; void sqr_it(tr ob) { ob.set_i(ob.get_i()*ob.get_i()); cout<<"copy of obj has i value of "<<ob.get_i()<<"\n"; } int main() { tr obj(10); sqr_it(obj); cout<<"But, obj.i is unchanged in main:"<<obj.get_i() << endl; return 0; }
值变化
#include <iostream.h> class tr { int i; public: tr(int n) {i=n;} void set_i(int n) {i=n;} int get_i() {return i;} }; void sqr_it(tr& ob) { ob.set_i(ob.get_i()*ob.get_i()); cout<<"copy of obj has i value of "<<ob.get_i()<<"\n"; } int main() { tr obj(10); sqr_it(obj); cout<<"But, obj.i is unchanged in main:"<<obj.get_i()<<endl; return 0; }
5.静态数据变量
在类定义中,若将一个数据成员说明为static,这种成员称为静态数据成员。无论建立多少个类的对象,都只有一个静态数据的副本。
静态数据属于类,因此可以使用
“类名::”
访问静态的数据成员。
静态数据成员不能在类中进行初始化,因为在类中不给它分配内存空间,必须在类外的其它地方提供定义。
#include <iostream.h> class Student { static int count; int StudentNo; public: Student() { count++; StudentNo=count; } void print() { cout<<"Student"<<StudentNo<<" "; cout<<"count="<<count<<endl; } }; int Student::count=0; int main() { Student Student1; Student1.print(); cout<<"-----------------------\n"; Student Student2; Student1.print(); Student2.print(); cout<<"-----------------------\n"; Student Student3; Student1.print(); Student2.print(); Student3.print(); cout<<"-----------------------\n"; Student Student4; Student1.print(); Student2.print(); Student3.print(); Student4.print(); return 0; }
C++支持静态数据成员的一个重要原因是可以不必使用全局变量。
6.静态成员函数
静态成员函数首先是一个成员函数,使用时要用“类名::”作为它的限定词,或指出它作用在哪个对象上;
其次,静态成员函数不属于特定的对象,要让一个静态成员函数去访问非静态成员,既麻烦又无实际意义。一般来说,静态成员访问的基本上是静态成员或全局变量
静态成员函数可以定义成内嵌的,也可以在类外定义,此时不要用static前缀。
使用静态函数的一个原因,是在建立对象之前处理静态数据成员。
静态成员函数中没有this指针。
一般而言,静态成员函数不访问类中的非静态成员。若确实需要,静态成员函数只能通过对象名(或指向对象的指针)访问该对象的非静态成员。
7.友元
为了在类的外部访问类的私有成员,需要寻找一种途径,在不放弃私有数据安全性的情况下,类的外部函数或其它类能够访问类的私有成员。
C++中用友元作为实现这个要求的辅助手段。
友元既可以是不属于任何类的一般函数,也可以是另一个类的成员函数,还可以是整个的一个类。
在类定义中声明友元函数,需要在其函数名前加上关键字friend,可以放在公有部分,也可以放在私有部分。友元函数的声明可以在类内部,也可以在类的外部。
友元函数通过直接访问对象的私有成员,提高了程序运行的效率,但同时破坏了数据的隐蔽性,降低了程序的可维护性,这与面向对象的设计思想是背道而驰的,因此使用友元应谨慎。