1 / 66

高级语言程序设计 第三章 C ++语言基础-对象

高级语言程序设计 第三章 C ++语言基础-对象. 周律. 教学目标. 类对象 构造函数 析构函数 拷贝构造函数 指针的概念 指向类成员的指针 指向类静态成员的指针 对象指针、 This 指针、常指针 等 对象的其它知识:常类型,子对象,动态内存的分配. 类对象. 为了使用类,还必须说明类的对象。在定义类时,系统是不会给类分配存储空间的,只有定义类对象时才会给对象分配相应的内存空间。 对象的定义格式: < 类名 > < 对象名表 > ;

gay-vang
Download Presentation

高级语言程序设计 第三章 C ++语言基础-对象

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 高级语言程序设计第三章 C++语言基础-对象 周律

  2. 教学目标 • 类对象 • 构造函数 • 析构函数 • 拷贝构造函数 • 指针的概念 • 指向类成员的指针 • 指向类静态成员的指针 • 对象指针、This指针、常指针等 • 对象的其它知识:常类型,子对象,动态内存的分配

  3. 类对象 为了使用类,还必须说明类的对象。在定义类时,系统是不会给类分配存储空间的,只有定义类对象时才会给对象分配相应的内存空间。 对象的定义格式: <类名> <对象名表>; 其中,<类名>是待定的对象所属的类的名字,即所定义的对象是该类的对象。<对象名表>中可以有一个或多个对象名,多个对象名用逗号分隔。在<对象名>中,可以是一般的对象名,还可以是指向对象的指针名或引用名,也可以是对象数组名。

  4. 对象成员 对象成员的表示方法 一个对象的成员就是该对象的类所定义的成员。对象成员有数据成员和成员函数。一般对象的成员表示如下: <对象名>.<成员名> 或者 <对象名>.<成员名>(<参数表>) 前者用于表示数据成员,后者用于表示成员函数。这里的“.”是一个运算符,该运算符的功能是表示对象的成员。

  5. 示例 #include <iostream.h> class myclass { public: int data1; }; void main() { myclass object1; object1.data1 = 25; cout << "\n data1的值是" << object1.data1<<"\n"; }

  6. 对象指针的成员 指向对象的指针的成员表示如下: <对象指针名>-><成员名> 或者 <对象指针名>-><成员名>(<参数表>) 同样,前者用于表示数据成员,后者用于表示成员函数。这里的“->”是一个表示成员的运算符,它与前面介绍过的“.”运算符的区别是:“->”用来表示指向对象的指针的成员,而“.”用来表示一般对象的成员。 对于数据成员和成员函数,以下两种表示方式是等价的: <对象指针名>-><成员名> 与 (*<对象指针名>).<成员名>

  7. 示例 #include <iostream.h> class myclass { public: int data1; }; void main() { myclass objact1; myclass *pObject1 = &objact1; pObject1->data1 = 25; cout << "\n data1的值是" <<pObject1->data1<<"\n"; }

  8. 构造函数 • 自动初始化对象的特殊的成员函数 • 与所属的类同名 • 可以在类中声明并定义构造函数,或在类中声明而在外部定义 • 构造函数没有返回类型 • 默认构造函数是不带任何参数的构造函数

  9. 示例1 class IMTI { public: IMTI(); //构造函数 }; IMTI() :: IMTI()() { }

  10. 示例2 class date{ int month, day, year; public: date() //默认构造函数 {day=1; month=1; year=1999;} date(int x) //仅指定日 {day=x; month=1; year=1999;} date(int x, int y, int z) //指定年月日 {day=x; month=y; year=z;} };

  11. 缺省构造函数 缺省构造函数是指不需要用户指定实参就能够被调用的构造函数,这并不意味着它不能接受实参。只意味着构造函数的每个参数都有一个缺省值与之关联。如: • Account::Account() { ... } • Stack::Stack( int size = 0 ) { ... } • Complex::Complex(double re=0.0,double im=0.0) { ... }

  12. 构造函数 编译器根据参数调用不同的构造函数 date now; date today(4); date all(23,3,1998);

  13. 析构函数 • 在对象销毁时自动调用的成员函数 • 编译器会生成对析构函数的调用 • 与类同名,但是在函数名前有个波浪号 (~) • 析构函数没有返回类型,也不带参数 • 一个类中只可能定义一个析构函数。

  14. 示例1 class imti { public: ~ imti(); //析构函数 }; IMTI() :: ~IMTI()() { }

  15. 示例2 #include<iostream.h> class Sample { public: Sample() {x = 0;} ~Sample() { cout<<"析构函数被调用!"<<endl; } int x; void Print() { cout<<"x = "<<x<<endl; } }; void main() { Sample s1; s1.Print(); s1.~Sample(); }

  16. 缺省析构函数 缺省析构函数的格式如下: • <类名>::~<缺省析构函数名>{ } • <缺省构析函数名>即为该类的类名。缺省析构函数是一个空函数

  17. 拷贝构造函数  在下列情况,会调用拷贝构造函数 • 把某个对象初始化为类的另一个对象时 • 将对象当作参数传递给函数时 • 函数返回对象时

  18. 拷贝构造函数 • 如果没有定义拷贝构造函数,编译器将自动生成一个 • 自动生成的拷贝构造函数只是将对象内容逐个字节地copy • 当数据成员有指针时,将导致两个对象的指针指向同一个地址

  19. 拷贝构造函数 定义 以对象的引用作为参数的构造函数 X::X(X &ptr) 或 X::X(const X &ptr) 使用 const 关键字,可以确保拷贝过程不会意外地更改源对象

  20. 示例1 #include<iostream.h> class TPoint { public: TPoint(int x, int y){ m_x = x; m_y = y;} TPoint(TPoint & p); ~TPoint(){cout<<"Destructor Called!\n";} int Xcoord() {return m_x;} int Ycoord() {return m_y;} private: int m_x, m_y; };

  21. 示例1(续) TPoint::TPoint(TPoint & p) { m_x = p. m_x; m_y = p. m_y; cout<<"Copy-initialization Constructor Called.\n,"; } void main() { TPoint p1(5, 7); TPoint p2(p1); cout<<"p2 = "<<p2.Xcoord()<<","<<p2.Ycoord()<<endl; }

  22. 示例2 #include<iostream.h> class TPoint { public: TPoint(int x, int y){ m_x = x; m_y = y; cout<<"now is beginning"<<endl; } TPoint(TPoint & p); ~TPoint(){cout<<"Destructor Called!\n";} int Xcoord() {return m_x;} int Ycoord() {return m_y;} private: int m_x, m_y; };

  23. 示例2(续) TPoint::TPoint(TPoint & p) { m_x = p. m_x; m_y = p. m_y; cout<<"Copy-initialization Constructor Called.\n,"; } TPoint F(TPoint q) { cout<<"ok\n"; int x, y; x = q.Xcoord() + 10; y = q.Ycoord() + 20; TPoint R(x, y); return R; } void main() { TPoint a(20, 35), b(0, 0); TPoint n(a); b=F(n); cout<<"b="<<b.Xcoord()<<","<<b.Ycoord()<<endl; }

  24. 内存 0 …... 2000 2001 2002 2003 2005 …... 指针的概念 内存中每个字节有一个编号-----地址 程序中: int i; float k; i 编译或函数调用时为其分配内存单元 k 变量是对程序中数据 存储空间的抽象

  25. …... 整型变量i 2000 10 2001 2002 2003 变量i_pointer 2004 2005 变量地址(指针) 指针变量 2006 地址存入 指针变量 指向 …... 变量值 变量 指针的概念 • 指针:一个变量的地址 • 指针变量:专门存放变量地址的变量叫~ 指针 变量的内容 变量的地址 2000 指针变量

  26. *i_pointer i_pointer 10 2000 &i_pointer i …... 整型变量i 2000 10 2001 2002 2003 变量i_pointer 2004 2000 指针变量 2005 2006 …... 指针的概念 含义:取指针所指向变量的内容 单目运算符 优先级: 2 结合性:自右向左 含义: 取变量的地址 单目运算符 优先级: 2 结合性:自右向左 • 两者关系:互为逆运算 • 理解 &与*运算符 含义 i_pointer &i &(*i_pointer) i *i_pointer *(&i) i_pointer=&i=&(*i_pointer) i=*i_pointer =*(&i) i_pointer-----指针变量,它的内容是地址量 *i_pointer----指针的目标变量,它的内容是数据 &i_pointer---指针变量占用内存的地址

  27. 面向对象元素与指针 指向类成员的指针 : • 指向数据成员的指针: <类型说明符><类名>::*<指针名>

  28. 示例 #include <iostream.h> class Test { private: int a; public: Test(int i) {a = i;} int c; int fun(int b){return a * c + b;} }; void main(){ int Test::*pc = &Test::c; Test object1(1); object1.*pc = 8; cout<<"object1.c is"<<object1.c<<endl; }

  29. 静态类成员指针 • 静态类成员是属于该类的全局对象和函数。 • 指向静态成员的指针,声明的方式和普通指针完全一样,只是赋值的时候,还得加上类的限定符:

  30. 示例 #include<iostream.h> class myclass { public: // 构造函数,每定义一个对象, 静态数据成员i加1 myclass() { ++i; } static int i; // 声明静态数据成员i }; int myclass::i=0; // 静态数据成员i初始化, 不必在前面加static void main() { int *count=&myclass::i; // 声明一个int型指针,指向类的静态成员 myclass ob1,ob2,ob3,ob4; cout<<"myclass::i= "<<*count<<endl; // 通过指针直接访问静态数据成员 }

  31. 指向成员函数的指针 • 指向数据成员的指针: <类型说明符>(<类名>::*<指针名>)(<参数表>)

  32. 示例 #include <iostream.h> class Test { private: int a; public: Test(int i) {a = i;} int c; int fun(){return a+ c;} }; void main(){ Test object1(1); int (Test::*pfun) (); pfun = &Test::fun; object1.c = 8; int x=1; cout<<"object1.*pfun is"<<(object1.*pfun)()<<endl; }

  33. 对象指针 1.用指针访问单个对象成员 声明对象指针的一般语法形式为: 类名* 对象指针名; 当用指向对象的指针来访问对象成员时, 要用“->”操作符。

  34. 示例 #include<iostream.h> class exe{ public: void set_a(int a){ x=a; } void show_a(){ cout<<x<<endl; } private: int x; }; int main() { exe ob,*p; // 声明类exe的对象ob和类exe的对象指针p ob.set_a(2); ob.show_a(); // 利用对象名访问对象的成员 p=&ob; // 将对象ob的地址赋给对象指针p p->show_a(); // 利用对象指针访问对象的成员 return 0; }

  35. 对象指针 2. 用对象指针访问对象数组 上例的main()改写为: int main() { exe ob[2],*p; ob[0].set_a(10); ob[1].set_a(20); p=ob; p->show_a(); p++; p->show_a(); return 0; }

  36. this指针 • This 指针是指向对象本身的指针,它隐含在类成员函数中,用来指向成员函数所属类的正在被操作的对象。 • 编译器会把对象的地址赋给成员函数中的this指针。确保访问到的数据成员属于这个对象 Date::Date(int y,int m,int d) { this -> year = y; this -> month = m; this -> day = d; } 注:静态成员函数没有this 指针

  37. this的用法 class person{ private: int age; public: void display(); }; void Person::display(){ this -> age = 25; // 与age = 25一样 cout << this -> age; // 与cout << age一样 cout << endl; }; int main(){ Person Jack; Jack.display(); return 0; }

  38. 对象数组 定义:对象数组是指数组元素为对象的数组,该数组中若干个元素必须是同一个类的若干个对象 。 对象数组定义格式如下: <类名><数组名>[<大小>] 比如:Date dates1[7];

  39. 示例 class Date { public: Date(int m, int d, int y); void Printf(); private: int m_month, m_day, m_year; }; Date dates[4]={ Date (4,22,2006),Date (4,23,2006), Date (4,24,2006),Date (4,25,2006)}

  40. 指针与数组 对于二维数组,又是如何用指针访问其中的每个数组元素的呢? 例如,定义了一个二维数组a: int a[3][5]; a是以一个3*5的二维数组,它有三行,每一行都有其起始地址。 C++语言规定以a[0],a[1],a[2]分别表示第0行,第1行,第2行的起始地址,即该行第0列元素的地址。注意a[0],a[1],a[2]并不是一个元素,而是一行首地址,正如同一维数组名是数组起始地址一样,a[0]的值等于&a[0][0],a[1]的值等于&a[1][0],a[2]的值等于&a[2][0]。在同一行中是同样的类推方式,比如:a[0]+1的值等于&a[0][1],a[1]+2的值等于&a[1][2],……。

  41. 数组指针 数组指针与指针数组 在C++语言中,数组指针就是一个指向数组的指针;指针数组就是其元素为指针的数组。在学习C++语言时,要注意对它们进行区分,不能等同起来。 1. 数组指针 数组指针是一个指向一维数组的指针变量,定义数组指针的格式为: 数据类型 (*指针名)[常量表达式];

  42. 数组指针 例如: int (*p)[5]; 上面这个语句定义了一个数组指针p,它指向一个包含5个元素的一维数组,数组元素为整型。注意,*p两侧的圆括号不能省略,它表示p先与星号“*”结合,是指针变量。如果省略了圆括号,即写成*p[5]的形式,由于方括号的优先级比星号高,则p先与方括号[ ]结合,是数组类型,那么语句int *p[5];是定义了一个指针数组。

  43. 指向对象数组的指针 指向对象数组的指针定义格式如下: <类名>(*PL)[4]; 其中,PL是指向数组的指针名,该指针是一个指向一维对象数组的指针,该数组中有4个元素,每个元素是指定<类名>的对象

  44. 指针数组 2. 指针数组 指针数组就是其元素为指针的数组。它是指针的集合,它的每一个元素都是指针变量,并且它们具有相同的存储类型和指向相同的数据类型。 说明指针数组的语法格式为: 数据类型 *指针数组名[常量表达式]; 其中,数据类型式指数组中各元素指针所指向的类型,同一指针数组中各指针元素指向的类型相同;指针数组名也即数组的首地址,是一个标识符;常量表达式指出这个数组中的元素个数。 例如:下面定义了几个指针数组。 int *p1[6]; float *p2[3][4];

  45. void指针 void指针 一般来说,只能用指向相同类型的指针给另一个指针赋值,而在不同类型的指针之间进行赋值是错误的。比如: int a,b; int *p1=&a,*p2=p1; //正确 而: int a; int *p1=&a; double *p2=p1; //错误 上述语句中的两个指针p1,p2指向的类型不同,因此,除非进行强制类型转换,否则它们之间不能相互赋值。但是void指针是一个特例。

  46. void指针 C++语言允许使用空类型(void)指针,即不指定指针指向一个固定的类型,它的定义格式为: void *p; 表示指针变量p不指向一个确定的类型数据,它的作用仅仅是用来存放一个地址。 void指针它可以指向任何类型的C++数据。也就是说,可以用任何类型的指针直接给void指针赋值。不过,如果需要将void指针的值赋给其他类型的指针,则需要进行强制类型转换。比如: int a; int *p1=&a; void *p2=p1; int *p4=(int *)p2;

  47. 对象的其它知识

  48. 常类型 常引用 如果在说明引用时用const修饰,则被说明的引用为常引用。 常引用的说明形式如下: const 类型说明符& 引用名 例如: int a=5; const int& b=a; 其中,b是一个常引用,它所引用的对象不允许更改。

  49. 实例 #include<iostream.h> int add(const int& i,const int& j); void main() { int a=20; int b=30; cout<<a<<"+"<<b<<"="<<add(a,b)<<endl; } int add(const int& i,const& j) { return i+j; }

  50. 常对象 如果在说明对象时用const修饰,则被说明的对象为常对象。 常对象的说明形式如下: 类名 const 对象名[(参数表)]; 或者 const 类名 对象名[(参数表)]; 在定义对象时必须进行初始化,而且不能被更新。

More Related