Cpp_Chapter8
课件谭浩强C++程序设计第8章(带特殊条款)
课件谭浩强C++程序设计第8章(带特殊条款)课件:谭浩强《C++程序设计》第8章概述:第8章主要介绍了C++中的继承和多态性。
继承是面向对象编程中的一种重要特性,它允许我们创建一个新的类(称为派生类),该类继承另一个类(称为基类)的属性和方法。
多态性则允许我们使用一个接口来定义多种不同类型的对象的行为。
本章将详细介绍这两个概念,并通过实例来演示它们的应用。
一、继承的概念与定义1.继承的基本概念继承是面向对象编程中的一种机制,允许我们创建一个新的类(派生类),该类继承另一个类(基类)的属性和方法。
派生类可以添加新的属性和方法,也可以覆盖基类的方法。
2.继承的定义在C++中,继承通过使用冒号和访问权限关键字(如public、protected和private)来定义。
例如,如果我们要创建一个派生类Student,它继承自基类Person,可以如下定义:cppclassPerson{public:stringname;intage;};classStudent:publicPerson{public:stringstudentId;};二、继承的访问权限1.公共继承(public)当一个类使用public关键字进行继承时,基类的public成员在派生类中仍然是public,protected成员在派生类中仍然是protected。
2.保护继承(protected)当一个类使用protected关键字进行继承时,基类的public和protected成员在派生类中都变为protected。
3.私有继承(private)当一个类使用private关键字进行继承时,基类的public和protected成员在派生类中都变为private。
三、继承中的构造函数和析构函数1.构造函数的继承在派生类中,构造函数会调用基类的构造函数,然后执行派生类自己的构造函数。
如果基类有默认构造函数,则可以省略基类构造函数的调用。
(完整word版)C++编程思想 答案 第八章 其他章节请点击用户名找 hinking in C++
[ Viewing Hints ] [ Book Home Page ] [ Free Newsletter ][ Seminars ] [ Seminars on CD ROM ] [ Consulting ]Annotated Solution GuideRevision 1.0for Thinking in C++, 2nd edition, Volume 1by Chuck Allison©2001 MindView, Inc. All Rights Reserved.[ Previous Chapter ] [ Table of Contents ] [ Next Chapter ] Chapter 88-1Create three const int values, then add them together to produce a value that determines the size of an array in an array definition. Try to compile the same code in C and see what happens (you can generally force your C++ compiler to run as a C compiler by using a command-line flag).(Left to the reader)8-2Prove to yourself that the C and C++ compilers really do treat constants differently. Create a global const and use it in a global constant expression; then compile it under both C and C++.Solution://: S08:GlobalConst.cppconst int n = 100;const int m = n + 2;int main() {} ///:~While this is a legal C++ program, C doesn’t allow expressions with const variables at the global level, so the above code will not compile in C. If you move the declaration of m inside of main( ), however, it works fine in C. But don’t let this make you think that you can do this for array declarations. Exercise 1 shows that you cannot use a const variable as an array dimension in C under any circumstances.8-3Create example const definitions for all the built-in types and their variants. Use these in expressions with other const s to make new const definitions. Make sure they compile successfully.(Left to the reader)8-4Create a const definition in a header file, include that header file in two .cpp files, then compile those files and link them. You should not get any errors. Now try the same experiment with C.(Left to the reader)8-5Create a const whose value is determined at runtime by reading the time when the program starts (you’ll have to use the <ctime> standard header). Later in the program, try to read a second value of the time into your const and see what happens.Solution://: S08:ConstTime.cpp#include <iostream>#include <ctime>using namespace std;const time_t now = time(0);int main() {cout << static_cast<long>(now) << endl;// now = time(0);// cout << static_cast<long>(now) << endl;}/* Output:949180534*////:~The first commented line is illegal because you can’t assign to const variables – they can only be initialized. I made the variable now global to emphasize an important difference between C and C++: you can initialize automatic variables at runtime in C, but not globals, like you can in C++. For example, the following C program works just fine://: S08:ConstTime.c#include <stdio.h>#include <time.h>int main() {const time_t now = time(0);printf("%ld", now);}/* Output:949180534*////:~If you move the definition of now outside of main( ), a C compiler will complain.8-6Create a const array of char, then try to change one of the char s.(Left to the reader)8-7Create an extern const declaration in one file, and put a main( ) in that file that prints the value of the extern const. Provide an extern const definition in a second file, then compile and link the two files together.(Left to the reader)8-8Write two pointers to const long using both forms of the declaration. Point one of them to an array of long. Demonstrate that you can increment or decrement the pointer, but you can’t change what it points to.(Left to the reader)8-9Write a const pointer to a double, and point it at an array of double. Show that you can change what the pointer points to, but you can’t increment or decrement the pointer.(Left to the reader)8-10Write a const pointer to a const object. Show that you can only read the value that the pointer points to, but you can’t change the p ointer or what it points to.(Left to the reader)8-11Remove the comment on the error-generating line of code in PointerAssignment.cpp to see the error that your compiler generates.(Left to the reader)8-12Create a character array literal with a pointer that points to the beginning of the array. Now use the pointer to modify elements in the array. Does your compiler report this as an error? Should it? If it doesn’t, why do you think that is?Solution://: S08:StringLiteral.cpp#include <iostream>int main() {using namespace std;char* word = "hello";*word = 'j';cout << word << endl;}/* Output:jello*////:~As explained in the book, even though string literals are arrays of const char, for compatibility with C you can assign them to a char*(“pointer to a non-const char”). You’re not supposed to be able to change a string literal (the standard says that any such attempt has undefined results), but most compilers run the program above the same. It’s certainly not a recommend pr actice.8-13Create a function that takes an argument by value as a const; then try to change that argument in the function body.(Left to the reader)8-14Create a function that takes a float by value. Inside the function, bind a const float& to the argument, and only use the reference from then on to ensure that the argument is not changed.(Left to the reader)8-15Modify ConstReturnValues.cpp removing comments on the error-causing lines one at a time, to see what error messages your compiler generates.(Left to the reader)8-16Modify ConstPointer.cpp removing comments on the error-causing lines one at a time, to see what error messages your compiler generates.(Left to the reader)8-17Make a new version of ConstPointer.cpp called ConstReference.cpp which demonstrates references instead of pointers (you may need to look forward to Chapter 11).Solution://: S08:ConstReference.cpp// Constant reference arg/returnvoid t(int&) {}void u(const int& cir) {int i = cir;}const int& w() {static int i;return i;}int main() {int x = 0;int& ir = x;const int& cir = x;t(ir);//! t(cir); // Not OKu(ir);u(cir);//! int& ip2 = w(); // Not OKconst int& cir2 = w();//! w() = 1; // Not OK} ///:~When comparing this program to ConstPointer.cpp in the book, notice first the omission of those statements that qualify the reference itself as const. While you can declare a pointer itself to be const (as opposed to a pointer-to-const), all references are implicitly const, because once bound to an object you can’t change that binding (more in Chapter 11). The commented-out statements are all const violations (i.e., you can’t assign via a reference-to-const).8-18Modify ConstTemporary.cpp removing the comment on the error-causing line to see what error messages your compiler generates.(Left to the reader)8-19Create a class containing both a const and a non-const float. Initialize these using the constructor initializer list.Solution://: S08:InitList.cpp#include <iostream>using namespace std;class HasFloats {const float x_;float y_;public:HasFloats(float x, float y): x_(x), y_(y){}void display() const {cout << "x == " << x_ << ", y == " << y_ << endl;}};int main() {HasFloats h(3,4);h.display();}/* Output:x == 3, y == 4*////:~You can initialize y_ in the body of the constructor if you wish, but const members like x_ must be initialized in the initializer list.8-20Create a class called MyString which contains a string and has a constructor that initializes the string, and a print( ) function. Modify StringStack.cpp so that the container holds MyString objects, and main( ) so it prints them.(Left to the reader)8-21Create a class containing a const member that you initialize in the constructor initializer list and an untagged enumeration that you use to determine an array size.(Left to the reader)8-22In ConstMember.cpp, remove the const specifier on the member function definition, but leave iton the declaration, to see what kind of compiler error message you get.(Left to the reader)8-23Create a class with both const and non-const member functions. Create const and non-const objects of this class, and try calling the different types of member functions for the different types of objects.(Left to the reader)8-24Create a class with both const and non-const member functions. Try to call a non-const member function from a const member function to see what kind of compiler error message you get.(Left to the reader)8-25In Mutable.cpp, remove the comment on the error-causing line to see what sort of error message your compiler produces.(Left to the reader)8-26Modify Quoter.cpp by making quote( ) a const member function and lastquote mutable. Solution:Here’s the modified class definition://: S08:Quoter.cpp {O}#include <iostream>#include <cstdlib>#include <ctime>using namespace std;class Quoter {mutable int lastquote;public:Quoter();int lastQuote() const;const char* quote() const;}; ///:~Don’t forget to add a const suffix to the definition of Quoter::quote( ) also. No other changes are necessary.8-27Create a class with a volatile data member. Create both volatile and non-volatile member functions that modify the volatile data member, and see what the compiler says. Create both volatile and non-volatile objects of your class and try calling both the volatile and non-volatile member functions to see what is successful and what kind of error messages the compiler produces.Solution://: S08:V olatile.cppclass V olatile {volatile int x;public:void mod1(int x) {this->x = x;}void mod2(int x) volatile {this->x = x;}};int main() {V olatile v1;volatile V olatile v2;v1.mod1(1);v1.mod2(2);//! v2.mod1(3); // Errorv2.mod2(4);} ///:~The only error is in attempting to call a non-volatile function for a volatile object. You might think that mod1( )would have trouble compiling, but it doesn’t. volatile is not exactly the same as const. Just remember that volatile means that something outside what is visible in the source code may modify an object (and so volatile declarations usually are pointers). There’s no problem with your code also modifying a volatile object like mod1( ) does.8-28Create a class called bird that can fly( ) and a class rock that can’t. Create a rock object, take its address, and assign that to a void*. Now take the void*, assign it to a bird*(you’ll have to use a cast), and call fly( )through that pointer. Is it clear why C’s permission to openly assign via avoid*(without a cast) is a “hole” in the language, which couldn’t be propagated into C++? Solution:This is the wh ole point of C++’s type system! You shouldn’t be able to accidentally misuse an object through pointer gyrations. If this were allowed, you could indirectly call any function at all for any object at all without the compiler complaining. Not a smart way to program.[ Previous Chapter ] [ Table of Contents ] [ Next Chapter ]Last Update:06/27/2002。
Cpp8
8.2.3 作为参数传递
当二维数组作为参数传递给函数时, 当二维数组作为参数传递给函数时,其意义也为内存 地址。 地址。 例:主函数中初始化一个矩阵并将每个元素都输出, 主函数中初始化一个矩阵并将每个元素都输出, 然后调用子函数,分别计算每一行的元素之和, 然后调用子函数,分别计算每一行的元素之和,将和直接 存放在每行的第一个元素中, 存放在每行的第一个元素中,返回主函数之后输出各行元 素的和。
8.3 字符数组
字符数组:用于存放字符的数组, 字符数组:用于存放字符的数组,每个元素存放一个字符 char c[10]; char string[32]; c[0]='A';c[1]='B';c[2]='C';… 字符数组的初始化: 字符数组的初始化: char c[10]={ 'A' , 'B' , 'C' , 'D'}; 二维数组的定义、初始化: 二维数组的定义、初始化:同一维数组 字符串:学习过字符串常量,可以用字符串常量对字符数组赋初值 字符串:学习过字符串常量, 字符串用一维字符数组存放 最后跟一个'\0' 空操作符 用一维字符数组存放, 字符串用一维字符数组存放,最后跟一个 char c[ ]={"this is a string."}; char c[ ]="this is a string."; char c[17]={'t','h','i','s',' ',……..};
int b,i=1,j=2; int a[10]; b=a[5]+a[7]+a[3*3]; b=a[0]-a[i*j];
C++程序设计教程第八章
第八章 指 针
C++语言拥有在运行时获得变量的地址和操纵地址的能 力,这种用来操纵地址的特殊类型变量就是指针. 8.1 指针的概念 1.指针类型 指针是一种操作地址的变量.每一种基本数据类型都 有相应的指针类型,如int, float, char, double等. 指针的类型实际上是指针指向的变量或常量的类型. 1.指针变量的定义 定义指针变量的一般形式为: 数据类型 * 指针变量名
时其地址的变化和指向的内容.
8
一般而言,指针的算术运算和关系运算有如下规 定: (1)指针和整型量的加减表示移动指针,以指向当前对 象前面或后面的某个位置的对象,即和整型量i的加减 作为指针值和i*sizeof(对象类型)的加减. (2)只有当两个指针变量指向同一个数组中的时候,才 可以进行减法运算,结果表示由第一个指针所指对象 开始至第二个指针所指对象(不包括该对象本身)之间的 对象个数. (3)当两个指针变量指向同一个数组中的时候,可以用 关系运算符>,= =,!=等进行比较.假定p1和p2是指 向同一数组中元素的指针,当p1所指的元素在p2所指 的元素之前时,p1<p2为真;当p1和p2指向同一元素时, p1= =p2为真.不允许指向不同数组的指针进行比较. 注意:无论何时,两个指针相加总是无意义的.
1
例如: int* ip ; //整型指针 char * icp ; //字符型指针 指向整型数的指针是包含该整型数地址的变量或常量. 上面两个指针定义都分配了空间,但是都没有指向任 何内容.正如定义整型或浮点变量没有给它赋值一样, 指针也没有被赋值. 每一个指针都有一个类型(void*除外).指针是变量, 因此它具有变量特性,因此它与其他基本数据类型一 样,凡可声明变量的地方,就可声明指针变量,它可 以是全局,静态全局,静态局部和局部的. 3. 建立指针 建立指针包括定义指针和给指针赋初值.例如: int * iPtr ; int iCount=18; iPtr=&iCount; //将地址赋给指针,即存放地址的变量
编译第8章
• 属性变量=属性表达式
1、属性文法定义
属性文法(attribute grammar)是一个三元 组:A=(G,V,F),其中 G:是一个上下文无关文法 V:有穷的属性集,每个属性与文法的一个终结符或非 终结符相连,这些属性代表与文法符号相关信息, 如它的类型、值、代码序列、符号表内容等等 .属 性与变量一样,可以进行计算和传递。属性加工 的过程即是语义处理的过程。 F:关于属性的属性断言或一组属性的计算规则(称为 语义规则) . 断言或语义规则与一个产生式相联,只 引用该产生式左端或右端的终结符或非终结符相 联的属性.
addtype
id3
addtype
例5-4:real id1,id2,id3 的分析树和属性计算
8.3 中间代码的形式
何谓中间代码: 源程序的一种内部表示,不依赖目标机的 结构,易于机械生成目标代码的中间表示。 为什麽要此阶段 逻辑结构清楚; 利于不同目标机上实现同一种语言; 利于进行与机器无关的优化; 这些内部形式也能用于解释;
• 语义处理
–例:变量的存储分配 –例:表达式的求值 –例:语句的翻译(中间代码的生成)
• 总目标:生成等价的中间代码
语义处理方法
• 对应每一个产生式编制一个语义子程序, 当一个产生式获得匹配时,调用相应的 语义子程序实现语义检查与翻译。 • 在产生式的右部的适当位置,插入相应 的语义动作,按照分析的进程,执行遇 到的语义动作。
8)若把语义子程序改成产生某种中间代 码的动作,就能在语法分析制导下,随 着分析的进展逐步生成中间代码。 9)若把语义子程序改成产生某种机器的 汇编语言指令,就能随着分析的进展逐 步生成某机器的汇编语言代码。
chapter 8 Objects and Classes (1)
{
实现对被调函数中对象数
cash = cash + amount;
据的修改。
}
void person::give ( int amount, person &somebody)
{ //给somebogy 现金amount
cash = cash - amount; //自己的现金减少
somebody.cash += amount; //对方现金增加
操作与数据之间依赖性强,每个操作都必须掌握数据结构的 操作细节,数据结构发生改变时,依赖此数据的所有操作都 需要修改;
模块之间耦合度高,需求变更时维护代价高昂;
数据开放,不可控的数据修改导致系统既不可靠也不 安全;
优点:运行性能高。
5
哈尔滨工业大学 计算机科学与技术学院
5
6
只要有了本解对数象据8的 存.2操 储作 结面构需向对象的程序设计
a.show(); b.show(); c.show(); boss.show(); waiter.show();
哈尔滨工业大学 计算机科学与技术学院
6
8.1.2 面向对象的程序设计
易维护、易复用、易扩展
符合我们认识客观世界的规律,降低了复杂系统分析和设计的 复杂性。
只有对象操作需要了解数据存储细节,其它对象访问此数据通 过调用此对象操作进行,因此不必了解数据存储的细节;
Public: 公有成员(类接口),程序的任何部分都可以访问。
哈尔滨工业大学 计算机科学与技术学院
13
210418/4/26
类体的定义
class 类名称 {
public : 公有(接口)成员
private: 私有成员
C语言教程8文件
磁盘
2011-1-20 《C与C++程序设计教程》-第八章
返回
8
8.2.2 文件的打开与关闭
系统自动打开和关闭的五个标准设备文件 标准设备文件: 标准设备文件
打开文件fopen
函数首部: 文件号 文件指针 标准文件 *fopen(char *filename,char *mode) 0FILE stdin 标准输入(键盘) 功能:按指定方式打开文件。 含义 1 标准输出(显示器) 文件使用方式 stdout 例:文件打开与测试。 要打开的文件名 返值:正常打开,为指向文件结构体的指针;打开 “r/rb”FILE *fp; (只读) stderr 2 标准错误(显示器) 为输入打开一个文本/二进制文件 失败,为NULL。 if(( fp=fopen(“filename”,“rb+”))==NULL) “w/wb” (只写) stdaux 为输出打开或建立一个文本/二进制文件 3 标准辅助(辅助设备端口) {(追加) printf(“cannot open this file\n”); “a/ab”4 向文本/二进制文件尾追加数据 stdprn 标准打印(打印机) exit(0); “r+/rb+” (读写) *fp; 为读/写打开一个文本/二进制文件 例} FILE “w+/wb+”fp= fopen (“c:\test”,”rb+”); (读写) 为读/写建立一个文本/二进制文件
缓冲文件系统:
不关闭文件可能会丢失数据
磁盘文件
输入文件缓冲区 程序数据区 a
输出文件缓冲区
fclose
返回
10
2011-1-20
《C与C++程序设计教程》-第八章
C语言第8章习题及答案
C语言第8章习题及答案(总10页)--本页仅作为文档封面,使用时请直接删除即可----内页可以根据需求调整合适字体及大小--第八章用一个数组存放图书信息,每本书是一个结构,包括下列几项信息:书名、作者、出版年月、借出否,试写出描述这些信息的说明,并编写一个程序,读入若干本书的信息,然后打印出以上信息。
#include <>typedef struct{char Name[20];char Author[20];int Date_Year;int Date_Month;int loaned;} BOOK;#define N 10void main(){BOOK books[N];int i;for (i=0;i<N;i++){printf("Input Book's Name:");gets(books[i].Name);printf("Input Book's Author:");gets(books[i].Author);printf("Input Book's Year of Publishing:");scanf("%d",&books[i].Date_Year);printf("Input Book's Month of Publishing:");scanf("%d",&books[i].Date_Month);printf("Input Book's Status, 1-Loaned, 2-Keepin:");scanf("%d",&books[i].loaned);}for (i=0;i<N;i++){printf("Book: %s, Author: %s, Publishing:%d-%d, Status:%d\n", books[i].Name, books[i].Author, books[i].Date_Year, books[i].Date_Month,books[i].loaned);}}编写一个函数,统计并打印所输入的正文中的各个英文单词出现的次数,并按次数的递减顺序输出。
第 8 章_指针
0067:FDFC
iPtr 0067:FE00 变量iCont 58 *iPtr
13
指针变量亦为变 量,因而它也具有 内存地址。
1-6. 指针与整型数的区别
指针变量中所存储的是地址值,不是整型数。
int iCount=26; int *iPtr=&iCount; *iPtr=&iCount; //error 不能将整型地址转换成整型数。 *iPtr=50;
x 的值是3
21
3.指针的++、 --、+=、-= 运算
++、 += :是移动指针到下一个或下几个存储单元。 --、 -= :是移动指针到上一个或上几个存储单元。 例如: int *ptr, ary[5]={2,4,6,8,10} ; ptr=ary; ptr+=3; ptr--;
22
2. 指针运算
想一想:*ptr++和(*ptr)++有什么 区别 ?
p++:等价于p=p+1,即指针变量p向高地址移动, 指针指向当前元素的下一个元素 *p++:由于++和*优先级相同,结合方向自右 而左,即*(p++),等价于{*p和p++}。 (*p)++:表示p所指向的元素值加1,等价于 *p=*p+1
《编译原理》第八章习题答案下载
四元式:
100 (+, a, b, t1) 101 (+, c, d, t2) 102 (*, t1, t2, t3) 103 (-, t3, /, t4) 104 (+, a, b, t5) 105 (+, t5, c, t6) 106 (-, t4, t6, t7)
树形:
盛威网()专业的计算机学习网站
如果题目是 S::=L.L | L L::=LB | B B::=0 | 1 则写成: S`::=S {print(S.val);} S::=L1.L2 { S.val:=L1.val+L2.val/2L2.length ;} S::= L { S.val:=L.val; } L::=L1B { L.val:=L1.val*2+B.val; L.length:=L1.length+1; } L::=B { L.val:=B.val; L.length:=1;} B::=0 { B.val:=0; } B::=1 { B.val:=1;}
答案:加入新的开始符号 S`和规则 S`ÆS,得到增广文法。语法制导定义如下:
产生式 S`ÆS SÆL1.L2 SÆL LÆL1B
LÆB
BÆ0 BÆ1
语义规则 print(S.val) S.val:=L1.val+L2.val/2L2.length S.val:=L.val L.val:=L1.val*2+B.val L.length:=L1.length+1 L.val:=B.val L.length:=1 B.val:=0 B.val:=1
end ELSE begin
E.type:=real IF E1.type=integer THEN
《C++程序设计简明教程(第二版)》 第8章流和文件
mode含义
r w a read 按只读方式打开文件。 write 按只写方式打开文件。 append 按附加方式打开文件。若文件不存在,则建立文件。若文件 存在,则在文件末尾增加新内容。
r+
w+ a+
按读写方式打开文件,只对原文件进行修改。
按读写方式打开文件,覆盖原文件。 按附加方式打开文件,与a相同。
输出
osb<<hex isb>>hex osb<<oct isb>>oct
osb<<endl
6
程序8.4 使用操纵符控制输出举例
#include<iostream.h> #include<iomanip.h> void main( ) { int i=100; double pi=3.14159265; cout<<i<<","<<hex<<i<<","<<oct<<i<<endl; cout<<setw(5)<<setfill('x')<<i<<endl; //设置域宽只对本次输出有效 cout<<dec <<setprecision(10) <<pi<<endl; cout <<setprecision(4) <<pi<<endl; } 程序输出结果: 100,64,144 xx144 3.1415926, 3.1416
2
C++预定义流
C 语言程序设计章 (8)
– 基类只有无参数构造函数 • 在基类具有无参构造函数,派生类又没有定义构造函数的时候,系统会自动 调用基类的无参构造函数来构造派生类对象中的基类成分。
派生类 子类
C++语言程序设计
9
8.1 继承的概念
• “派生”(Derive)可以理解为继承的另外一种说法。
– “类D继承了类B”可以表述为“类B派生出类D”。 – 若类B派生出类D1、D2…,也可以说B是D1、D2…的泛化
(Generalization),称B为D1、D2…的基类,称D1、D2为B的派生 类。
何成员。
20
8.2 定义基类和派生类
• 私有继承和保护继承的区别
孙类成员函数无法访问
父类
public: protected:
private:
private
子类
private: private private
private protected public
孙类
private: private private
protected:
继承方式决定继承
?
private:
成员的访问权限
?
C++语言程序设计
18
8.2 定义基类和派生类
1. 公有继承
公有继承的派生类定义形式: class 派生类名:public 基类名 {
派生类新成员定义;
};
基类
public: protected: private:
派生类对象
Cpp_8多态性0
friend complex operator + (complex c1, complex c2);
friend complex operator - (complex c1, complex c2); void display();
private:
double real; double imag; }
c.imag=c2.imag+ imag;
return complex (c.real, c.imag); } complex complex::operator - (complex c2 ) { complex c c.real=real-c2.real; c.imag=imag-c2.imag; return complex (c.real, c.imag); }
第八章 多态性
本章主要内容
• 滞后联编和运行时的多态性
• 虚函数
• 纯虚函数和抽象类
• 设计举例
(8-2)
多态性的概念
• 多态性是面向对象程序设计的重要特征之一。 • 多态性是指发出同样的消息被不同类型的对 象接收时导致完全不同的行为。 • 消息-主要指对类的成员函数的调用。 • 多态的实现: – 函数重载(静态) – 运算符重载(静态) – 虚函数(动态)
(8-27)
早期联编与滞后联编
早期联编(早期束定)
–联编工作出现在编译阶段,用对象名 或者类名来限定要调用的函数。
滞后联编
–联编工作在程序运行时执行,在程序 运行时才确定将要调用的函数。
(8-28)
早期联编例 #include<iostream.h> class Point { public: Point(double i, double j) {x=i; y=j;} double Area() const{ return 0.0;} private: double x, y; }; class Rectangle:public Point { public: Rectangle(double i, double j, double k, double l); double Area() const {return w*h;} private: double w,h; (8-29) };
vc++第8章
内存单元的地址 内存单元的内容
Page 4
指针的使用目的
使程序简洁、紧凑、 使程序简洁、紧凑、高效 有效地表示复杂的数据结构 有效方便地使用数组和字符串 动态分配内存 得到多于一个的函数返回值
Page 5
&与*运算符
含义: 含义: 含义 取变量的地址 含义 取指针所指向变量的内容 • 两者关系:互为逆运算 两者关系: 单目运算符 单目运算符 i_pointer • 理解 优先级: 优先级: 优先级 2 优先级 2 &i_pointer 2000 结合性:自右向左 结合性:自右向左 结合性 自右向左 结合性 自右向左 …... 2000 2001 2002 2003 2004 2005 2006 …... 2000 变量i 变量 _pointer 指针变量 短整型变量i *i_pointer 10 i
(1)符号“*”表示这种变量是指针变量; 符号“ 表示这种变量是指针变量; 指针变量的值只能是某一个变量的地址( (2)指针变量的值只能是某一个变量的地址(起 始地址); 始地址); (3)编译程序为指针变量分配内存单元(4个字 编译程序为指针变量分配内存单元( 节); 定义指针变量时, (4)定义指针变量时,其类型定义了指针变量所 指向的数据类型, 指向的数据类型,该类型确定了数据占用的 存储空间的大小。 存储空间的大小。 (5)可对指针变量进行初始化
Page 3
计算机内存的存储
内存用户数据区 2000H 2001H 2002H 2003H 00101100 00000001
short i; 如果有
变量 i cin >>i; 输入 300; 即 i = 00000001 00101100B
char a; 如果有
C++程序设计基础课后答案 第八章复习课程
C++程序设计基础课后答案第八章8.1 阅读下列程序,写出执行结果1. #include <iostream.h>class Bclass{ public:Bclass( int i, int j ) { x = i; y = j; }virtual int fun() { return 0 ; }protected:int x, y ;};class Iclass:public Bclass{ public :Iclass(int i, int j, int k):Bclass(i, j) { z = k; }int fun() { return ( x + y + z ) / 3; }private :int z ;};void main(){ Iclass obj( 2, 4, 10 );Bclass p1 = obj;cout << p1.fun() << endl;Bclass & p2 = obj ;cout << p2.fun() << endl;cout << p2.Bclass :: fun() << endl;Bclass *p3 = &obj;cout << p3 -> fun() << endl;}2. #include <iostream.h>class Base{ public:virtual void getxy( int i,int j = 0 ) { x = i; y = j; }virtual void fun() = 0 ;protected:int x , y;};class A: public Base{ public:void fun(){ cout<<"x = "<<x<<'\t'<<"y = x * x = "<<x*x<<endl; } };class B:public Base{ public:void fun(){ cout << "x = " << x << '\t' << "y = " << y << endl;cout << "y = x / y = " << x / y << endl;}};void main(){ Base * pb;A obj1;B obj2;pb = &obj1;pb -> getxy( 10 );pb -> fun();pb = &obj2;pb -> getxy( 100, 20 );pb -> fun();}8.2 思考题1.在C++中,使用类体系依靠什么机制实现程序运行时的多态?2.如果一个基类的虚函数被声明为私有成员函数,会有语法错误吗?可以在应用类体系时实现动态联编吗?请你验证一下。
c++大学基础教程课后答案
第八章类和对象8.1 构造函数是什么?什么时候执行它?构造函数是类的一个特殊的成员函数,它负责实现对象的创建和初始化工作。
构造函数在对象被创建的时候由系统自动调用执行。
8.2 构造函数有返回类型吗?没有。
8.3 什么时候调用析构函数?当对象消失时,系统自动调用析构函数来释放对象所占的内存空间。
8.4 假定一个类叫做Test,说明怎样声明一个构造函数,它带一个叫做count 的int 参数。
Test::Test(int count){;}8.5 拷贝构造函数与赋值运算符(=)有何联系与区别?拷贝构造函数就是函数的形参是类的对象的引用的构造函数,拷贝构造函数用来复制一个对象。
通过等于号复制对象时,系统会自动调用拷贝构造函数。
8.6 能否给对象数组赋初值?能。
8.7 类和对象的区别是什么?一个类表示现实生活中的一类事物,是抽象的,对象是一类事物中的一个具体的个体,即对象是类的一个具体的实例,类和对象的关系相当于普遍与特殊的关系。
在C++中,类是一个自定义的数据类型,对象是该数据类型的一个变量。
8.8 如果通过值将对象传递给函数,就会创建对象副本。
函数返回时是否销毁该副本?是。
8.9 什么时候,系统调用拷贝构造函数?拷贝构造函数在以下三种情况下都会被调用:(1)用类的一个对象去初始化该类的另一个对象时。
(2)如果函数的形参是类的对象,调用函数时,进行形参和实参结合时。
37(3)如果函数的返回值是类的对象,函数执行完成返回调用者时。
8.10 什么叫做静态数据成员?它有何特点?在类声明时,采用static 关键字来声明的数据成员叫静态数据成员;它的特点是:每个类只有一个拷贝,由该类的所有对象共同维护和使用,从而实现了同一类的不同对象之间的数据共享。
8.11 什么叫做友员函数?什么叫做友员类?友员关系是否可以传递?友元函数是在类声明中由关键字friend 修饰的非成员函数。
在类的声明中可以由关键字friend 声明另一个类为本类的友元,这时称为友元类。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
• 可以看到声明类的方法是由声明结构体 类型的方法发展而来的。
17
上海财经大学信息管理与工程学院
• 对于四边形可以这样声明一个包括数据 操作类:
•class CRectangle •{ •private : • int x; • int y; •public: • int area() //定义area类函数 • { • return (x*y); • } • void set_values(int a,int b) //定义set_values类函数 • { • x = a; • y = b; •• 也可以看作声明结构体类型的方法发展 } •}; 而来的。 , rectb; •CRectangle rect
12
上海财经大学信息管理与工程学院
8.1.4 类和对象的作用
• 对一个大型任务来说,面向对象程序设 计方法是十分有效的,增加 了软件可扩 充性和可重用性,它能大大降低程序设 计人员的工作难度,减少出错机会,减 少了软件维护的难度。
13
上海财经大学信息管理与工程学院
8.2 类的声明和对象的定义
8.2.1 类和对象的关系
16
上海财经大学信息管理与工程学院
• 它只包括数据,没有包括数据操作。现 在声明一个包括数据操作类:
class Student { //以class开头
private :
int num; char name[20]; char sex; public: void display( ) //这是成员函数 { cout<<"num:"<<num<<endl; cout<<"name:"<<name<<endl; cout<<"sex:"<<sex<<endl; //以上4行是函数中的操作语句 } }; Student stud1, stud2; // 定义了两个Student 类的对象stud1和stud2 //以上3行是成员数据
}; Student stud1, stud2; //定义了两个Student 类的对象
20
上海财经大学信息管理与工程学院
• 对于四边形类的声明改为:
•class CRectangle •{ •private : • int x; • int y; •public: • int area() //定义area类函数 • { • return (x*y); • } • void set_values(int a,int b) //定义set_values类函数 • { • x = a; • y = b; • } •}; •CRectangle rect , rectb;
11
上海财经大学信息管理与工程学院
8.1.3 面向对象的软件开发
• 面向对象的软件工程包括以下几个部分: 1. 面向对象分析(object oriented analysis,OOA) 2. 面向对象设计(object oriented design,OOD) 3. 面向对象编程(object oriented programming, OOP) 4. 面向对象测试(object oriented test,OOT) 5. 面向对象维护(object oriented soft maintenance, OOSM)
10
上海财经大学信息管理与工程学院
• 在面向过程的结构化程序设计中,人们常使用 这样的公式来表述程序: 程序=算法+数据结构 • 基于对象程序设计所面对的是一个个对象,把 一个算法和一组数据结构封装在一个对象中, 所有的数据分别属于不同的对象 ,程序的操作 是围绕对象进行的。因此,就形成了新的观念: 对象 = 算法 + 数据结构 程序 = (对象+对象+对象+…) + 消息 或: 程序 = 对象s 信息管理与工程学院
可以将上面Student类的声明改为
• • • • • • • • • • • • • • • class Student { private: //声明类类型
//声明以下成员数据部分为私有的 int num; char name[20]; char sex; public: //声明以下成员函数部分为公用的 void display( ) { cout<<"num:"<<num<<endl; cout<<"name:"<<name<<endl; cout<<"sex:"<<sex<<endl; }
14
上海财经大学信息管理与工程学院
8.2.2 声明类类型
• 在C++中声明一个类类型和声明一个结构体类 型是相似的。 • 下面是声明一个结构体类型的方法:
•
struct student
{
int num; char name[20]; char sex;
//声明了一个名为student的结构体类型
}; student stud1,stud2; //定义了两个结构体变量stud1和stud2
• 抽象是从我们需要解决的问题出发,在与该问题相关 的一组关联对象中提取出主要的或共有的部分。 • 抽象的作用是表示同一类事物的本质。例如,数据类 型就是对一批具体的数的抽象。 • 类是对象的抽象,而对象则是类的特例,或者说是类 的具体表现形式。
7
上海财经大学信息管理与工程学院
4. 继承与重用 • “白马”继承了“马”的基本特征,又增加了 新的特征(颜色),“马”是父类,或称为基类, “白马”是从“马”派生出来的,称为子类或 派生类。 • 如果在软件开发中已经建立了一个名为A的 “类”,又想另外建立一个名为B的“类”, 而后者与前者内容基本相同,只是在前者的基 础上增加一些属性和行为,这就是面向对象程 序设计中的继承机制。 • 利用继承可以简化程序设计的步骤。 • C++提供了继承机制,采用继承的方法可以很 方便地利用一个已有的类建立一个新的类。这 就是常说的“软件重用” 的思想。
6
上海财经大学信息管理与工程学院
3. 抽象
• 如一个三角形可以作为一个对象,10个不同尺寸的三 角形是10个对象。如果这10个三角形对象有相同的属 性和行为,可以将它们抽象为一种类型,称为三角形 类型。在C++中,这种类型就称为“类(class)”。这10 个三角形就是属于同一“类”的对象。
• 我们把这种能够抽象地描述某一些具有共性的 物体的词称为类(Class)。
上海财经大学信息管理与工程学院
第8章 类和对象
8.1 8.2 8.3 8.4 8.5 8.6 面向对象程序设计方法概述 类的声明和对象的定义 类的成员函数 对象成员的引用 类的封装性和信息隐蔽 类和对象的简单应用举例
1
上海财经大学信息管理与工程学院
8.1 面向对象程序设计方法概述
• 到目前为止,编程方法采用面向过程、 按顺序进行的机制,程序必须有一个完 整的开始、处理和结束过程, 即前面的方 法是面向过程的程序设计方法。 • 对于规模比较小的程序,编程者可以直 接编写出一个面向过程的程序,详细地 描述每一瞬时的数据结构及对其的操作 过程。 • 但是当程序规模较大时,就显得力不从 心了。
8
上海财经大学信息管理与工程学院
5. 多态性
• 在C++中,所谓多态性(polymorphism)是指: 由 继承而产生的相关的不同的类,其对象对同一 消息会作出不同的响应,分别执行不同的操作。 这种情况就是多态现象。 • 在Windows环境下,用鼠标双击一个文件对象 (这就是向对象传送一个消息),如果对象是一个 可执行文件,则会执行此程序,如果对象是一 个文本文件,则启动文本编辑器并打开该文件。 • 多态性是面向对象程序设计的一个重要特征, 能增加程序的灵活性。
15
上海财经大学信息管理与工程学院
• 对于一个四边形,同样可以声明一个名 为cRectangle的结构体类型和定义两个结 构体变量rect, rectb
– – – – – – struct cRectangle //声明一个名为cRectangle的结构体类型 { int x; int y; }; cRectangle rect, rectb; //定义了两个结构体变量rect, rectb
• 正如同结构体类型和结构体变量的关系一样, 人们先声明一个结构体类型,然后用它去定义 结构体变量。 • 在C++中也是先声明一个类类型,然后用它去 定义若干个同类型的对象。对象就是类类型的 一个变量。 • 可以说类是对象的模板,是用来定义对象的一 种抽象类型。 • 类是抽象的,不占用内存,而对象是具体的, 占用存储空间。在一开始时弄清对象和类的关 系是十分重要的。
5
上海财经大学信息管理与工程学院
2. 封装与信息隐蔽 • 可以对一个对象进行封装处理,把它的一部分 属性和功能对外界屏蔽,也就是说从外界是看 不到的,甚至是不可知的。这样做的好处是大大 降低了操作对象的复杂程度。 • 所谓“封装”,指两方面的含义: 一是将有关 的数据和操作代码封装在一个对象中,形成一 个基本单位,各个对象之间相对独立,互不干 扰。二是将对象中某些部分对外隐蔽,只留下 少量接口,以便与外界联系,接收外界的消息。 这种对外界隐蔽的做法称为信息隐蔽 (imformation hiding)。信息隐蔽还有利于数据 安全,防止无关的人了解和修改数据。
上海财经大学信息管理与工程学院
• 面向对象的程序设计就是以 上的思路。 • 设计一个复杂的软件系统时, 首要的问题是确定该系统是 由哪些对象组成的,并且设 计这些对象。
函数 (操作代码,行為)