




已阅读5页,还剩67页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第五章第五章多态性和虚函数多态性和虚函数 5 1多态性 多态性 polymorphism 的定义 的定义 一 定义 多态性 一 定义 多态性 能够呈现不同形态的特性和状态 能够呈现不同形态的特性和状态 polymorphism the quality or state of being able to assume different forms 摘 摘 自自 Webster 词典 词典 二 二 两种多态性两种多态性 1 编译时的多态性编译时的多态性 亦称静态联编 束定 亦称静态联编 束定 static binding 或早期联编或早期联编 early binding 即本章中前半部分将要讲述的函数和运算符 即本章中前半部分将要讲述的函数和运算符 函数函数 的重载 编译系统的重载 编译系统 进行编译时在函数调用指令表中找到多个重载的函数中相对应的一个函数 即形进行编译时在函数调用指令表中找到多个重载的函数中相对应的一个函数 即形 参的数量和类型完全匹配的那个函数 参的数量和类型完全匹配的那个函数 将它们与主程序中调用它们的代码联编 将它们与主程序中调用它们的代码联编 binding 以备主程序运行时正确地调用 这在 以备主程序运行时正确地调用 这在 C 中这表现为 中这表现为 行为共享行为共享 例如同名函数实现不同功能 例如同名函数实现不同功能 或称 或称 同一接口 多种方法同一接口 多种方法 2 所谓运行时的多态性所谓运行时的多态性 亦称所谓动态联编 束定 亦称所谓动态联编 束定 dynamic binding 或滞后联编或滞后联编 late binding 编译系统进行编译时 根据程序代码内容 按照运行时被动态 编译系统进行编译时 根据程序代码内容 按照运行时被动态 地确定的地确定的 this 指针 找到相应的虚函数 将它与主程序中调用它的代码联编指针 找到相应的虚函数 将它与主程序中调用它的代码联编 binding 以供主程序在运行中调用它 本章后半部分将详细讲解 以供主程序在运行中调用它 本章后半部分将详细讲解 5 2函数重载 函数重载 overloading 5 2 1普通函数的重载普通函数的重载 C C 语言中一个函数只能处理一个类型的数据 或者只能处理整型数据 或者只能处理语言中一个函数只能处理一个类型的数据 或者只能处理整型数据 或者只能处理 doubledouble 浮点型数据 不可能兼顾两种或多种数据类型 浮点型数据 不可能兼顾两种或多种数据类型 能否使用一个函数来处理多个类型的数据 这可以在面向对象程序设计语言中解能否使用一个函数来处理多个类型的数据 这可以在面向对象程序设计语言中解 决 在决 在 C 中可用一个函数名 中可用一个函数名 sq 来处理所有参数类型的平方 例子如下 来处理所有参数类型的平方 例子如下 例例 1 平方函数的重载 两个单形参的重载函数平方函数的重载 两个单形参的重载函数 overld fun1 cpp overloading of functions include double sq double y return y y int sq int y return y y void main int i 5 double d 5 5 cout sq i endl cout sq d endl Results 25 30 25 例例 2 求最大值函数的重载 三个双形参的重载函数求最大值函数的重载 三个双形参的重载函数 overld fun2 cpp overloaded function for determining max value include include int max int x int y return x y x y double max double x double y return x y x y char max char x char y return strcmp x y 0 x y void main cout max 9 4 endl cout max 4 5 7 4 endl cout max Windows MS DOS endl Results 9 7 4 Windows 在使用重载的普通函数时 应注意避免如下所示的二义性 在使用重载的普通函数时 应注意避免如下所示的二义性 ambig 3 cpp not working difference only in return type is not enough include void fun int y y int fun int y return y error void fun int overloaded function differs only by return type from int fun int error fun redefinition different basic types void main int i 5 cout fun i endl Not working 以上例子中 两个重载的普通函数只有返回值不同 而其他参数都相同 这是不以上例子中 两个重载的普通函数只有返回值不同 而其他参数都相同 这是不 够的 将引起二义性 出现编译错误 这是因为系统完全根据函数的参数表来选择够的 将引起二义性 出现编译错误 这是因为系统完全根据函数的参数表来选择 重载函数中相应函数的 重载函数中相应函数的 5 2 2构造函数的重载构造函数的重载 任何函数都能重载 构造函数也能重载 有时必须重载 现看几个例子 任何函数都能重载 构造函数也能重载 有时必须重载 现看几个例子 例例 1 输入不同格式时间值的重载构造函数输入不同格式时间值的重载构造函数 overld cons 1 cpp overloaded constructor copied from Wang s book p 108 109 include include 包含包含 atoi p 的函数原型的函数原型 class timer int seconds public timer 零形参构造函数零形参构造函数 timer int 单形参构造函数单形参构造函数 timer int int 双形参构造函数双形参构造函数 timer char 字符指针形参构造函数字符指针形参构造函数 int gettime timer timer 零形参构造函数零形参构造函数 seconds 0 timer timer int t 单形参构造函数单形参构造函数 seconds t timer timer int min int sec 双形参构造函数双形参构造函数 seconds min 60 sec timer timer char p 字符形参构造函数字符形参构造函数 seconds atoi p ASCII to integer int timer gettime return seconds void main timer t1 t2 56 t3 1 18 t4 123 cout 零值时间值零值时间值 t1 gettime endl cout 单个形参时间值单个形参时间值 t2 gettime endl cout 双形参时间值双形参时间值 t3 gettime endl cout 字符值时间值字符值时间值 t4 gettime endl Results 零值时间值零值时间值 0 单个形参时间值单个形参时间值 56 双形参时间值双形参时间值 78 字符值时间值字符值时间值 123 例例 2 不同初始化操作的构造函数不同初始化操作的构造函数 cons arr 1 cpp Arrays of objects are created include class A int a b public A A int i int j A void Set int i int j a i b j A A a b 0 cout No arg cons a a b b endl A A int i int j a i b j cout Constructor a a b b endl A A cout Destructor a a b b endl void main cout Starting first round n A obja 3 for int i 0 i 3 i obja i Set i i 1 cout Finishing first round n cout Starting second round n A objb 3 A 5 6 A 7 8 A 9 10 cout Finishing second round n cout Program being terminated n Results Starting first round No arg cons a 0 b 0 No arg cons a 0 b 0 No arg cons a 0 b 0 Finishing first round Starting second round Constructor a 5 b 6 Constructor a 7 b 8 Constructor a 9 b 10 Finishing second round Program being terminated Destructor a 9 b 10 Destructor a 7 b 8 Destructor a 5 b 6 Destructor a 2 b 3 Destructor a 1 b 2 Destructor a 0 b 1 以上程序中 语句以上程序中 语句 A objb 3 A 5 6 A 7 8 A 9 10 在建立对象数组在建立对象数组 objb 3 时 时 花括号内所建立的三个对象花括号内所建立的三个对象 A 5 6 A 7 8 A 9 10 就是对象数组的三个单元 这个形就是对象数组的三个单元 这个形 式相当于普通数组的以下表达式 式相当于普通数组的以下表达式 int arr 3 1 2 3 在定义重载的构造函数时 必须防止如下例所示的二义性 在定义重载的构造函数时 必须防止如下例所示的二义性 ambig 4 cpp may cause ambiguity in overloading constructors include class A int X Y public A X 0 Y 0 cout Cons 1 X Y endl A int x 10 int y 20 X x Y y cout Cons 2 X Y endl A cout Destructor X Y endl void main A obj1 3 6 A obj2 5 A obj3 error A A ambiguous call to overloaded function Results Cons 2 3 6 Cons 2 5 20 Destructor 5 20 Destructor 3 6 5 3运算符重载运算符重载 在面向对象程序设计语言中 运算符也是一种函数 所以运算符也能像函数一样在面向对象程序设计语言中 运算符也是一种函数 所以运算符也能像函数一样 给予重载 以便完成更多功能 系统所提供的预定义运算符只能用于预定义类型数给予重载 以便完成更多功能 系统所提供的预定义运算符只能用于预定义类型数 据的各种运算 对于用户自定义类型数据的各种运算 经常须要用户自己定义重载据的各种运算 对于用户自定义类型数据的各种运算 经常须要用户自己定义重载 的运算符 的运算符 以加法运算符以加法运算符 为例 预定义加法运算符为例 预定义加法运算符 只能用于预定义类型数据的加只能用于预定义类型数据的加 法运算 例如 法运算 例如 int x 1 y 2 z z x y 但此预定义运算符无法用于将同一个类的两个对象的变量分别相加 这必须依靠但此预定义运算符无法用于将同一个类的两个对象的变量分别相加 这必须依靠 用户自己定义的重载运算符函数 如下述 用户自己定义的重载运算符函数 如下述 5 3 1 算术运算符重载算术运算符重载 5 3 1 1重载运算符的友元函数形式重载运算符的友元函数形式 重载的运算符函数的任务是将对象中的全部或部分数据 包括私有数据 进行算重载的运算符函数的任务是将对象中的全部或部分数据 包括私有数据 进行算 术运算 然后将运算所得的值返回至某个对象的数据中 术运算 然后将运算所得的值返回至某个对象的数据中 上一节所讲普通函数的重载形式无法满足此要求 因为普通函数和主函数一样 上一节所讲普通函数的重载形式无法满足此要求 因为普通函数和主函数一样 无权访问对象的私有数据成员 无权访问对象的私有数据成员 因此 为了访问对象中的私有数据 就不能再采取普通函数的形式 而必须采取因此 为了访问对象中的私有数据 就不能再采取普通函数的形式 而必须采取 友元函数或该类的成员函数的形式友元函数或该类的成员函数的形式 先看友元函数形式 见下例 先看友元函数形式 见下例 例例 1 以友元函数形式重载加法运算符 以便访问类的私有数据以友元函数形式重载加法运算符 以便访问类的私有数据 overld friend 1 cpp operators overloaded in friend function format include class point int x y public point int vx 0 int vy 0 x vx y vy friend point operator point friend point operator point 此处不能返回局部变量的引用此处不能返回局部变量的引用 void print cout x y endl point operator point p x p1 x p2 x p y p1 y p2 y return p point operator point p x p1 x p2 x p y p1 y p2 y return p void main point p1 10 10 p2 20 20 p1 print p1 p1 p2 即即 p1 operator p1 p2 p1 print p2 p1 p2 即即 p2 operator p1 p2 p2 print Results 10 10 30 30 10 10 可注意到 可注意到 在友元函数形式中 该运算符函数的形参数量和该运算符在友元函数形式中 该运算符函数的形参数量和该运算符 的的 操作数的数量是相等的 操作数的数量是相等的 在上例中 这些运算符函数都具有两个形参 在上例中 这些运算符函数都具有两个形参 试问 编译系统怎么知道何时调用预定义运算符试问 编译系统怎么知道何时调用预定义运算符 或或 何时调用重载运 何时调用重载运 算符算符 或或 这完全根据操作数类型来确定这完全根据操作数类型来确定 如操作数是预定义类型 则调用 如操作数是预定义类型 则调用 预定义运算符预定义运算符 例如 例如 int j k s s j k 如操作数是用户自定义类型 如上例中类的对象如操作数是用户自定义类型 如上例中类的对象 p1 和和 p2 则调用重载运算 则调用重载运算 符符 例如 例如 coordinate p1 5 5 p2 10 10 p1 p1 p2 在以上主程序中在以上主程序中 是由是由 C 系统提供的 但有些情况下将会要求用户自 系统提供的 但有些情况下将会要求用户自 己定义重载的己定义重载的 运算符 以后有例 运算符 以后有例 上例中重载的运算符函数的返回值是对象而不是对象引用 因为临时对象上例中重载的运算符函数的返回值是对象而不是对象引用 因为临时对象 p 的引的引 用可能出现用可能出现 悬挂引用悬挂引用 如欲使用对象引用为返回值 则可将此临时对象 如欲使用对象引用为返回值 则可将此临时对象 p 定义为静定义为静 态对象 如下 态对象 如下 point p x p1 x p2 x p y p1 y p2 y return p 再看稍微复杂些的例子 向量 以复数形式表示 的算术运算 再看稍微复杂些的例子 向量 以复数形式表示 的算术运算 现有第一向量现有第一向量 c a bi 和第二向量和第二向量 z x yi c z a x b y i c z a x b y i c z a x b y a y b x i c z a x b y b x a y i x x y y 如果要进行加法运算 则可定义数组如 如果要进行加法运算 则可定义数组如 double dd 6 并令并令 dd 0 a dd 1 b dd 2 x dd 3 y 再写个函数再写个函数 add double arr dd 4 dd 0 dd 2 dd 5 dd 1 dd 3 则加法结果为则加法结果为 dd 4 dd 5 i 这样太麻烦了 能不能直接使用 这样太麻烦了 能不能直接使用 形式 这可依靠重载的运算符 形式 这可依靠重载的运算符 例例 2 用友元函数形式重载复数算术运算符用友元函数形式重载复数算术运算符 overld complex 1 cpp copied from Wang s book p 118 119 include class complex double real imag 复数的实数和虚数部分复数的实数和虚数部分 public complex double r double i real r imag i complex real 0 imag 0 void print friend complex operator complex plus friend complex operator complex minus void complex print cout 0 cout 显示实部与虚部之间的显示实部与虚部之间的 号 如虚部为负则不显示号 如虚部为负则不显示 if imag 0 cout imag i 显示虚部 如为零则省略它显示虚部 如为零则省略它 cout endl 显示回车符显示回车符 complex operator complex temp real a real b real temp imag a imag b imag return temp complex operator complex temp real a real b real temp imag a imag b imag return temp void main complex c1 3 6 2 8 c2 2 3 2 8 c3 c1 print c2 print c3 c1 c2 c3 print c3 c1 c2 c3 print Results 3 6 2 8i 2 3 2 8i 5 9 5 6i 1 3 5 3 1 2重载运算符的成员函数形式重载运算符的成员函数形式 重载运算符时 既可具有友元函数形式 也可具有成员函数形式 重载运算符时 既可具有友元函数形式 也可具有成员函数形式 在在 5 3 1 1 例例 1 的友元函数形式的重载加法运算符中 位于的友元函数形式的重载加法运算符中 位于 p x p1 x p2 x 语句的语句的 赋值等号右侧的是两个对象赋值等号右侧的是两个对象 p1 和和 p2 的数据成员的数据成员 x 我们可以采用成员函数形式 我们可以采用成员函数形式 定义它为第一个操作数即对象定义它为第一个操作数即对象 p1 的成员函数 由的成员函数 由 p1 来调用此重载的运算符函数 来调用此重载的运算符函数 则重载运算符函数的函数体内的则重载运算符函数的函数体内的 p1 x 也可表达为也可表达为 x 而主函数也能以成员函数形式 而主函数也能以成员函数形式 调用该对象调用该对象 p1 的加法运算符函数 即的加法运算符函数 即 p1 operator p1 p2 成员函数的形式可从 成员函数的形式可从 以下表达式简化 以下表达式简化 point point operator point p1 point p2 point p p x p1 x p2 x p y p1 y p2 y return p 此处此处 point 表示此运算符函数是表示此运算符函数是 class point 的成员函数 既然是对象的成员函数 既然是对象 p1 调用此调用此 重载的运算符函数 函数中的两个语句重载的运算符函数 函数中的两个语句 p x p1 x p2 x p y p1 y p2 y 即可简化为 即可简化为 p x x p2 x p y y p2 y 这样一来 整个运算符函数的定义成为 这样一来 整个运算符函数的定义成为 point point operator point p2 形参形参 p1 可取消可取消 point p p x x p2 x p y y p2 y return p 以此方式 可将以上以此方式 可将以上 5 3 1 1 例例 1 程序改写为如下的成员函数形式程序改写为如下的成员函数形式 主函数仍保持不 主函数仍保持不 变 变 overld member 1 cpp program on p 114 115 of Wang Yan s book include class point int x y public point x 0 y 0 point int vx int vy x vx y vy point operator point point operator point void print cout x y x p x temp y y p y return temp point point operator point temp x x p x temp y y p y return temp void main point p1 10 10 p2 20 20 p3 p3 print p3 p1 p2 即即 p3 p1 operator p2 p3 print p3 p3 p1 即即 p3 p3 operator p1 p3 print Results 0 0 30 30 20 20 此处此处 operator 已是成员函数 已是成员函数 p1 和和 p2 是它的实参 也是此运算符的操作是它的实参 也是此运算符的操作 数 但表现形式和普通函数不同 实际上数 但表现形式和普通函数不同 实际上 p1 p2 是如下的函数调用 是如下的函数调用 p1 operator p2 位于重载运算符函数左面的是调用该运算符的对象 而运算符右面的对象是该运位于重载运算符函数左面的是调用该运算符的对象 而运算符右面的对象是该运 算符的实参 因此 作为类的成员函数的算符的实参 因此 作为类的成员函数的运算符的形参数目比它的操作数少一个 运算符的形参数目比它的操作数少一个 再重复以前提到的 根据什么来区别预定义的加法运算符和重载的加法运算符呢 再重复以前提到的 根据什么来区别预定义的加法运算符和重载的加法运算符呢 唯一的根据是操作数的类型 唯一的根据是操作数的类型 预定义的加法运算符的操作数是预定义的数据类型 预定义的加法运算符的操作数是预定义的数据类型 而重载的加法运算符的操作数则是类的对象 而重载的加法运算符的操作数则是类的对象 还须提及 由于一般情况下运算符函数都须要访问类的私有数据成员 所以极大还须提及 由于一般情况下运算符函数都须要访问类的私有数据成员 所以极大 多数重载的运算符函数都采用成员函数形式或者友元函数形式 多数重载的运算符函数都采用成员函数形式或者友元函数形式 5 3 1 3用于字符的加法运算符重载用于字符的加法运算符重载 字符串相接字符串相接 concatenation 的运算用于将两个字符串衔接起来 的运算用于将两个字符串衔接起来 C 语言中已有库函数语言中已有库函数 char strcat str1 str2 用于将字符串用于将字符串 str2 衔接于字符串衔接于字符串 str1 之后 能否使用简单的加法运算符将两个字符串衔接起来 这可以依靠重载的之后 能否使用简单的加法运算符将两个字符串衔接起来 这可以依靠重载的 运算符运算符 来实现来实现 strcat 的功能 使用起来就很方便 事实上 在的功能 使用起来就很方便 事实上 在 MFC 编程中 编程中 class CString 中就提供了重载的运算符函数 其函数原型为 中就提供了重载的运算符函数 其函数原型为 friend CString AFXAPI operator const CString 但这在通常的但这在通常的 C C 编程中无法使用 我们只能自己定义如下 编程中无法使用 我们只能自己定义如下 例例 1 用用 c a b 形式实现形式实现 strcat 的功能的功能 overld str 7 cpp include include class str char string 80 public str char strin strcpy string strin 是构造函数缺省值是构造函数缺省值 为空串 不能用单引号为空串 不能用单引号 然后还须将它复制入然后还须将它复制入 string str operator str str operator char s void show str void cout string endl str str operator str strcpy temp string string 第一串第一串 strcat temp string s string 接上第二串接上第二串 也即将也即将 s string 接至接至 temp string 中本对象中本对象 string 之后之后 return temp str str operator char s str temp strcpy temp string string 第一串第一串 strcat temp string s 接上第二串接上第二串 也即将也即将 s 接至接至 temp string 中字符串中字符串 string 之后之后 return temp void main str a Hello b friends str d char c world d a b 调用第一重载函数 即调用第一重载函数 即 d a operator b d show str d a c 调用第二重载函数调用第二重载函数 d show str Results Hello friends Hello world 5 3 1 4除法运算符重载除法运算符重载 用户自己在定义重载的运算符函数时 可以让它完成各类运算要求 例如现在 用户自己在定义重载的运算符函数时 可以让它完成各类运算要求 例如现在 在除法运算中 希望避免使用零除数 因这将得出不合理的运算结果 可以通过重在除法运算中 希望避免使用零除数 因这将得出不合理的运算结果 可以通过重 载的除法运算符来防止不合理运算 载的除法运算符来防止不合理运算 例例 1 overld div 1 cpp include class division public division double i numerator i double operator double denominator 成员函数形式成员函数形式 double numerator double division operator double denominator if denominator 0 cout 分母为零 请再输入分母分母为零 请再输入分母 return 999999 return numerator denominator void main double numerator denominator double result bool flag true cout numerator denominator while flag division num numerator result num denominator 由对象由对象 num 调用运算符函数调用运算符函数 i e result num operator denominator if result 999999 cin denominator else cout 商数为商数为 result endl flag false while Two kinds of results 1 请输入分子和分母请输入分子和分母 18 9 商数为商数为 2 2 请输入分子和分母请输入分子和分母 18 0 分母为零 请再输入分母分母为零 请再输入分母 9 商数为商数为 2 以上重载的运算符函数中 当输入分母值为零时 运算符函数返回值为以上重载的运算符函数中 当输入分母值为零时 运算符函数返回值为 999999 此非善策 更好方案请见第七章 此非善策 更好方案请见第七章 7 2 1 抛出异常抛出异常 中的中的 例例 1 5 3 2下标运算符下标运算符 重载重载 在声明在声明 int ptr new int 10 时 如果误写为时 如果误写为 1000 则将浪费大量空间 此外 则将浪费大量空间 此外 在使用数组中必须防止越限 如在使用数组中必须防止越限 如 ptr 1 或或 ptr 10 都是越限 后者最易出错 这可通都是越限 后者最易出错 这可通 过下标运算符过下标运算符 的重载来防止 的重载来防止 例例 1 由构造函数检查数组长度并在必要时改正 以及由重载的运算符由构造函数检查数组长度并在必要时改正 以及由重载的运算符 检查使用中检查使用中 的越限并在必要时终止程序 的越限并在必要时终止程序 overld 2 cpp Array size check if size is wrong it is re adjusted by the constructor and range error results in abnormal program termination by operator include include lower and upper limits of array size const MIN 10 const MAX 10000 或或 enum min 10 max 10000 class Vector int p int sz array length public Vector int size if sizeMAX size size MIN MAX MIN cout Size error New size is size endl p new int size sz size cout constructor endl Vector delete p cout destructor 0 else cout Wrong range i endl cout Program abnormally terminated endl Vector Vector very important exit 1 void main int size cout size Vector ve size ve 8 8 i e ve operator 8 8 then ve p 8 8 cout ve 8 endl ve 30 30 cout ve 30 endl 1 First kind of results Input size 40 constructor 8 30 destructor 2 Second kind of results Input size 5 Size error New size is 10 constructor 8 Wrong range 30 Program abnormally terminated destructor 5 3 3对象赋值运算符重载对象赋值运算符重载 第三章第三章 3 3 3 对象非静态数据成员的复制对象非静态数据成员的复制 中提到 中提到 C 系统所提供的赋值运系统所提供的赋值运 算符算符 的功能是将赋值号右面的原有对象的所有非静态数据内容的功能是将赋值号右面的原有对象的所有非静态数据内容逐域 逐个 复制逐域 逐个 复制 到赋值号左面的同一类新对象中 到赋值号左面的同一类新对象中 但它无法用于复制不同类对象间的数据成员 此但它无法用于复制不同类对象间的数据成员 此 时必须使用由用户定义的重载赋值运算符 请注意 时必须使用由用户定义的重载赋值运算符 请注意 赋值运算符只能重载为成员函赋值运算符只能重载为成员函 数 并且不能被继承 数 并且不能被继承 例例 1 一个对象复制另一个类对象的部分数据成员一个对象复制另一个类对象的部分数据成员 overld 3 cpp to show that overloading of operator is necessary include class A int X Y Z public friend class B A int a int b int c X a Y b Z c void GetX Y Z cout X Y Z endl class B int X Y public B X 0 Y 0 B void GetX Y cout X Y endl B Y p Y cout overloaded assignment operator called n return this void main A obja 10 20 30 obja GetX Y Z B objb objb GetX Y objb obja objb GetX Y Results 10 20 30 0 0 overloaded assignment operator called 10 20 在复制字符串时 如果进行在复制字符串时 如果进行 new 操作 则情况比较复杂 见以下数例 操作 则情况比较复杂 见以下数例 例例 2 同一类的两个对象中字符串内容的复制同一类的两个对象中字符串内容的复制 overld str 3 cpp To show the change of character array size in different objects include include class string char ptr int size public string char s size strlen s 1 ptr new char size strcpy ptr s string delete ptr void show cout ptr endl void operator string void string operator string void main string s1 Smith s2 You 1 s1 show 2 s2 show 3 cout s1 s2 endl 4 s1 s2 5 s1 show 6 s2 show 7 Results Smith You s1 s2 You You 此处暗藏了一个越界的危险 如果主函数中使用此处暗藏了一个越界的危险 如果主函数中使用 s2 s1 则出现危险 即则出现危险 即 s2 ptr 所指向的空间只能容纳所指向的空间只能容纳 You 而现在用来容纳 而现在用来容纳 Smith 因而越界 产生 因而越界 产生 Debug error 为解决此问题 在进行复制时必须重新从堆区中分配空间 见下例 为解决此问题 在进行复制时必须重新从堆区中分配空间 见下例 例例 3 解决越界危险的问题 在进行复制时重新从堆区中分配空间 同时能防止自身解决越界危险的问题 在进行复制时重新从堆区中分配空间 同时能防止自身 复制操作 复制操作 overld str 5 cpp re alloacate space in heap during assignment To show the change of character array size 与与 overld str 3 cpp 不同之处用蓝色标出不同之处用蓝色标出 include include class string char ptr int size public string char s size strlen s 1 ptr new char size strcpy ptr s string delete ptr void show cout ptr endl void operator string void string operator string return the case of s1 s1 cout Old size is size endl delete ptr release old space in heap ptr new char size str size 先将先将 size 赋值 再去堆区分配所需空间赋值 再去堆区分配所需空间 strcpy ptr str ptr cout The size has been changed to size endl void main string s1 Smith s2 You 1 s1 show 2 s2 show 3 cout s1 s1 endl 4 s1 s1 5 cout s2 s1 endl 6 s2 s1 7 s1 show 8 s2 show 9 Results 2 Smith 3 You 4 s1 s1 5 Self copying no operation 6 s2 s1 7 Old size is 4 The size has been changed to 6 8 Smith 9 Smith 以上程序中以上程序中 delete ptr release old space in heap 这一语句用于解决悬挂指针 这一语句用于解决悬挂指针 dangling pointer 的问题 用于在堆区内分配新的 的问题 用于在堆区内分配新的 空间之前 释放原来占用的堆区空间 空间之前 释放原来占用的堆区空间 双区存储内容双区存储内容 主程序第一句主程序第一句 string s1 Smith s2 You s1 栈区 栈区 堆区堆区 s2 栈区 栈区 Y o u 0 s2 ptrs1 ptr S m i t h 0 主程序第七句主程序第七句 s2 s1 s1 栈区 栈区 堆区堆区 s2 栈区 栈区 例例 4 不同对象的数据成员之间的组合加减 不同对象的数据成员之间的组合加减 overld 1 cpp Overloading of combined addition and combined subtraction operators include class number int num public number int n 1 constructor num n number add num s number sub num s int display const return num Addition of two data members of two objects of the same class S m i t h 0 s2 ptrs1 ptr S m i t h 0 number i e num num obj num return this enables cascading Subtraction of two data members of two objects of the same class number i e num num obj num return this enables cascading Driver for class number void main number n1 3 n2 7 n3 cout n1 num is n1 display endl cout n2 num is n2 display endl cout n3 num is n3 display endl n1 n2 cout After n1 n2 n1 num is n1 display endl n2 n3 cout After n2 n3 n2 num is n2 display endl Results n1 num is 3 n2 num is 7 n3 num is 1 After n1 n2 n1 num is 10 After n2 n3 n2 num is 6 5 3 4自增和自减运算符重载自增和自减运算符重载 共有四种自增 共有四种自增 incremental 和自减 和自减 decremental 运算符 即前置 运算符 即前置 pre 即即 i 和和 i 和后置 和后置 post 即即 i 和和 i 的自增和自减运算符 先看它们对预定义类型的自增和自减运算符 先看它们对预定义类型 数据的运算 数据的运算 例例 1 inc dec cpp Ordinary pre and post incremental and decremental operators include void main int i j 10 i j post increment 先用后加 结果 先用后加 结果 i 10 j 11 cout i i j j endl pre increment j 先加后用 结果先加后用 结果 j 12 j 20 i j pre decrement 先减后用 结果 先减后用 结果 i 19 j 19 cout i i j j endl post decrement 先用后减 结果显示 先用后减 结果显示 i 19 j 19 i 最后减为最后减为 18 Results i 10 j 12 i 19 j 19 它们也都可以被重载 先介绍编译器如何识别前置和后置的自增和自减运算符 它们也都可以被重载 先介绍编译器如何识别前置和后置的自增和自减运算符 为识别重载的前置和后置的运算符 每个重载的运算符函数必须有一个明确的特征 为识别重载的前置和后置的运算符 每个重载的运算符函数必须有一个明确的特征 以使编译器能确定需要使用的增量版本 重载前置增量的方法与重载其它前置一元运算以使编译器能确定需要使用的增量版本 重载前置增量的方法与重载其它前置一元运算 符相同 符相同 例如 当编译器遇到前置自增表达式例如 当编译器遇到前置自增表达式 d1 时 编译器就会生成时 编译器就会生成 成员函数调用成员函数调用 d1 operatot 为区别前置和后置自增运算符函数 为区别前置和后置自增运算符函数 VC 6 0 采用的方法是 当编采用的方法是 当编 译器遇到后置自增表达式译器遇到后置自增表达式 d1 时 就会生成时 就会生成 成员函数调用成员函数调用 d1 operator 0 其中 其中 0 是一个伪值 是一个伪值 pseudo value 它使运算符函数 它使运算符函数 operator 在用于后置自增操作和前置自在用于后置自增操作和前置自 增操作时有所区别 增操作时有所区别 例例 2 类的数据成员的前置自增和后置自增运算符的重载类的数据成员的前置自增和
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 考研忘记上传资料(3篇)
- 居民委员会的岗位试题及答案
- 安全消防知识试卷题库大全及答案解析
- 白酒制曲工设备维护与保养考核试卷及答案
- 大客安全文明考试题库及答案解析
- 护理口述答题题库大全集及答案解析
- 成考护理类题库及答案解析
- 南通安全员c2考题题库及答案解析
- 空调工安全培训测试题及答案解析
- 2025年儿童常见传染病预防知识试题及答案
- “一网统管”在城市治理协同中的障碍与解决路径研究
- 2025至2030中国电线电缆行业十四五发展分析及投资前景与战略规划报告
- 2025至2030全球与中国氘代化合物行业市场发展现状及竞争格局与前景预测报告
- 子宫肌瘤教学查房
- 过敏性休克抢救及处理流程
- 拆迁商铺置换协议书
- 《当代建筑设计理念》课件
- DB2303T 021-2024柞蚕脓病防治技术规程
- 煤矿事故汇报程序
- 化工联锁知识课件
- 空白个人简历表格模板
评论
0/150
提交评论