类的初始探究
----------------------- 析构函数---------------------------------------
析构函数名也应与类名相同,只是在函数名前面加一个位取反符~,例如~stud( ),以区别于
构造函数。它不能带任何参数,也没有返回值(包括void类型)。只能有一个析构函数,不能重
载。如果用户没有编写析构函数,编译系统会自动生成一个缺省的析构函数(即使自定义了析构
函数,编译器也总是会为我们合成一个析构函数,并且如果自定义了析构函数,编译器在执行时
会先调用自定义的析构函数再调用合成的析构函数),它也不进行任何操作。所以许多简单的类
中没有用显式的析构函数。
----------------------- 显示定义复制构造函数-----------------------
#include <iostream> #include <cstring> using namespace std; class Computer { private: char *brand; float price; public: Computer(const char *sz,float pce) { brand=new char[strlen(sz)+1]; strcpy(brand,sz); price=pce; } Computer(const Computer &cp) //自定义复制构造函数 { brand=new char[strlen(cp.brand)+1]; //重新为brand开辟与cp.brand同等大小的动态内存 strcpy(brand,cp.brand); //字符串复制 price=cp.price; } ~Computer() { delete[] brand; cout<<"清理现场"<<endl; } void print() { cout<<"品牌:"<<brand<<endl; cout<<"价格:"<<price<<endl; } }; int main() { Computer comp1("Dell",7000); comp1.print(); Computer comp2(comp1); //调用复制构造函数声明Computer类对象comp2,并用comp1为其初始化
// 相当于 Computer comp2=comp1; comp2.print(); return 0; }
---------------- const数据成员的初始化-----------------------------------------------
const关键字修饰的成员变量只能在初始化列表中进行初始化
#include <iostream> #include <cstring> using namespace std; class Point { private: const int xPos; const int yPos; public:
// 初始化表的顺序取决于成员声明的顺序,若yPos的声明在前,xPos的声明在后,
// 则以下初始化语句应先初始化 yPos(y),后初始化 xPos(x); Point (int x,int y):xPos(x),yPos(y) // const 数据成员只能在初始化表中初始化 { } //const 数据成员只能在初始化表中进行初始化,对复制构造函数来说同样如此 Point(const Point &cpt):xPos(cpt.xPos),yPos(cpt.yPos) { } void print() { cout<<"("<<xPos<<","<<yPos<<")"<<endl; } }; int main() { Point pt1(3,4); pt1.print(); Point pt2(pt1); //相当于Point pt2=pt1; pt2.print(); return 0; }
---------------- 引用数据成员的初始化-----------------------------------------------
对于引用类型的数据成员,同样只能通过成员初始化表达式进行初始化
#include <iostream> #include <cstring> using namespace std; class Point { private: int xPos; int yPos; int& ref1; double& ref2; public: Point(int x,int y,double & z):ref1(xPos),ref2(z) //引用成员的初始化同样要放在初始化表中 { xPos=x; yPos=y; } //复制构造函数与此一致:引用成员的初始化同样要放在初始化表中 Point(const Point& pt):ref1(pt.ref1),ref2(pt.ref2) { xPos=pt.xPos; yPos=pt.yPos; } void print() { cout<<"xPos: "<<xPos<<", yPos: "<<yPos<<endl; cout<<"ref1: "<<ref1<<", ref2: "<<ref2<<endl; } void SetX(int x) { xPos=x; } }; int main() { double outInt=5.0; Point pt1(3,4,outInt); pt1.print(); Point pt2(pt1); // 相当于 Point pt2=pt1; pt2.print(); cout<<"改变pt1中的x后"<<endl; pt1.SetX(7); pt1.print(); pt2.print(); outInt=6; cout<<"outInt变化后:"<<endl; pt1.print(); pt2.print(); return 0; }
---------------- 类对象成员的初始化-----------------------------------------------
#include <iostream> #include <cstring> using namespace std; class point //点类的定义 { private: int xPos; int yPos; public: point(int x=0,int y=0) //带缺省调用的构造函数 { cout<<"点的构造函数被执行"<<endl; xPos=x; yPos=y; } point(const point& pt) //复制构造函数 { cout<<"点的复制构造函数被执行"<<endl; xPos=pt.xPos; yPos=pt.yPos; } void print() { cout<<"( "<<xPos<<", "<<yPos<<")"; } }; class line //line类的定义 { private: point pt1; //point类对象作为line类成员,此处若写成point pt1(3,4),错 point pt2; public: line(int x1,int y1,int x2,int y2):pt1(x1,y1),pt2(x2,y2) //line对象的有参构造函数 { cout<<"线的构造函数被执行"<<endl; } line(const line& ll):pt1(ll.pt1),pt2(ll.pt2) //line对象的复制构造函数 { cout<<"线的复制构造函数被执行"<<endl; } void draw() { pt1.print(); cout<<" to "; pt2.print(); cout<<endl; } }; int main() { line l1(1,2,3,4); //调用有参构造函数 l1.draw(); line l2(l1); //调用复制构造函数 l2.draw(); return 0; }
-----------------------------静态成员函数的用法-----------------------------------------------------
(1) 静态成员函数既可以定义为 inline 的,如“ static void print_total()”,又可以定义在函数
外部,如“ void computer::print(computer& com) ”,在类定义之外时,不能用 static 。
(2) 静态成员函数不与特定的对象联系,基本的调用格式如下所示:
类名::静态成员函数名(参数表);
静态成员函数也可以由类的对象来访问,如:
comp1.print_total(); 和 comp2.print_total();
#include <iostream> #include <cstring> using namespace std; class computer { private: char* name; float price; static float total_price; //静态数据成员 public: computer(const char* chr,const float p) //构造函数,模拟买电脑操作 { name=new char[strlen(chr)+1]; strcpy(name,chr); price=p; total_price+=p; } ~computer() //析构函数,模拟退掉电脑的操作 { delete[] name; total_price-=price; } static void print_total() //静态成员函数,原则上只能访问静态数据成员 { cout<<"总价:"<<total_price<<endl; } static void print(computer& com); //静态成员函数print()原型,如果要访问某具体对象,必须传递参数 }; void computer::print(computer& com) //静态成员函数print()实现 { cout<<"名称: "<<com.name<<endl; cout<<"价格: "<<com.price<<endl; } float computer::total_price=0; //静态成员的初始化 int main() { computer comp1("IBM",7000); //声明类对象comp1,初始化,买入 computer::print(comp1); //类名加作用域限定符访问statci成员函数,传递参数comp1 computer::print_total(); //类名加作用域限定符访问statci成员函数 computer comp2("ASUS",4999); //声明类对象comp2,初始化,买入 computer::print(comp2); //类名加作用域限定符访问statci成员函数,传递参数comp2 computer::print_total(); comp2.~computer(); //析构函数调用,退还电脑 computer::print_total(); return 0; }
-----------------------------const成员函数及const对象的用法---------------------------------------
const成员函数表示该成员函数只能读类数据成员,而不能修改类成员数据。如果const成员
函数试图以任何方式改变类的数据成员或调用另一个非const成员函数,编译器将给出错误信息。
类对象也可以声明为const对象,一般来说,能作用与const对象的成员函数除了构造函数
和析构函数外,便只有const成员函数了,因为const对象只能被创建、撤销以及只读访问,改
写是不允许的。
#include <iostream> using namespace std; class point //类定义 { int x; //默认private型成员变量x和y int y; public: point(int xp=0,int yp=0)//构造函数 { x=xp; y=yp; } void SetX(int xp) //非const成员函数SetX,设置x { x=xp; } void SetY(int yp) //非const成员函数SetY,设置y { y=yp; } void print() const //const成员函数print,不能修改x和y { cout<<"x: "<<x<<" ,y: "<<y<<endl; } };
//或者
// void print() const;
// void point::print() const
//{
// cout<<"x:"<<x<<" ,y"<<y<<endl; int main() { point pt(3,4); //声明一个普通类变量pt pt.SetX(5); //使用pt可调用非const成员函数 pt.SetY(6); pt.print(); //pt也可调用const成员函数 const point ptC(1,2); //声明一个const对象(类变量) //ptC.SetX(8); //错误,ptC是const对象,只能调用const成员函数 //ptC.SetY(9); //错误,ptC是const对象,只能调用const成员函数 ptC.print(); //正确,const对象只能调用const成员函数 return 0; }