图2.3对象stu1和stu2实际上,类Student的所有成员函数放在公用区中,每个函数代码有一个地址,类Student的每个对象中只存放自己的数据成员值和指向公共区中对应函数的地址,也就是说,类的成员函数是共享的,如图2.4所示,这种对象的存储空间分配方式不仅节省了存储空间,而且各个对象的数据成员分别存放,互不相干。......
2023-11-07
在第2章中讨论过类对象的存储组织,每一个对象都占用一块存储空间,其中仅存放该对象的非静态数据成员,而静态数据成员以及成员函数则整个类才存放一份。
派生类的对象不仅存放了在派生类中定义的非静态数据成员,而且也存放了从基类中继承下来的所有非静态数据成员,因而在派生类中存放的这些从基类继承下来的数据存储又称派生类对象的子对象。
注意,即使基类中的私有数据成员不能继承到派生类中,但C++编译系统也为派生类对象分配基类中这些私有数据的存储空间。这种做法在大多数情况下并不会引起太大的内存占用问题。
例如,有以下程序:
上述程序中声明了一个类A,从该类派生出类B(属单继承的情况),这两个类中有一个同名的私有数据成员tag。程序的执行结果如下:
A:no=1,name=张三,tag=56
A:no=2,name=李四,tag=100
B:tag=200(www.chuimin.cn)
a:20
b:24
从结果看到,类A有3个私有数据成员,其对象a所占存储空间大小为18(sizeof(no)+sizeof(name)+sizeof(tag)),类B是从类A公有派生,尽管B∷tag与A∷tag重名,但A∷tag也占用类B对象的存储空间,所以类B对象b所占存储空间大小为22(=sizeof(A∷no)+sizeof(A∷name)+sizeof(A∷tag)+sizeof(B∷tag)),但由于A∷no,A∷name和A∷tag均为基类的私有成员,所以在类B中不能访问它们。
在main函数中,执行a.setvaluea(1,"张三",56);b.setvalueb(2,"李四",100,200);两个语句后,对象a和b的存储空间分配如图6.8所示。
图6.8 对象a和b的存储空间分配
与非静态数据成员存储方式不同,基类与派生类的静态数据成员与成员函数是共享的。在整个类层次中,基类A中定义的成员函数setvaluea和dispa以及派生类B中定义的成员函数setvalueb和dispb等都只保存一份代码。当派生类B对象使用从基类A继承下来的setvaluea和dispa成员函数时,编译系统会自动将这一调用映射到基类存放的代码。
有关C++程序设计基础教程的文章
图2.3对象stu1和stu2实际上,类Student的所有成员函数放在公用区中,每个函数代码有一个地址,类Student的每个对象中只存放自己的数据成员值和指向公共区中对应函数的地址,也就是说,类的成员函数是共享的,如图2.4所示,这种对象的存储空间分配方式不仅节省了存储空间,而且各个对象的数据成员分别存放,互不相干。......
2023-11-07
需要注意的是,基类指针虽然获取了派生类对象的地址,但只能访问派生类从基类继承的成员,不能访问派生类中新增的成员,除非对基类指针强制类型转换调用派生类的成员函数。......
2023-11-07
所以,在定义派生类的构造函数时除了对自己的数据成员进行初始化外,还必须负责调用基类构造函数使基类的数据成员得以初始化。如果派生类中还有子对象,还应包含对子对象初始化的构造函数。最后执行派生类的构造函数。其中,如果派生类新增成员中有某个类的子对象,第步的调用才会执行,否则就直接跳转到第步,执行派生类的构造函数。在某些情况下,派生类构造函数的函数体可能为空,仅起到参数传递作用。......
2023-11-07
如同一个变量一样,对象从被创建到被释放为止的时间称为对象的生存期。一个对象的生存期如图2.8所示。从上看到,分配对象的内存空间和调用构造函数进行数据成员初始化是两个不同的阶段。构造函数帮助对象自动进行初始化,并且初始化的同时可以执行其他操作。......
2023-11-07
程序设计是指设计、编写和调试程序的方法与过程。由于程序是软件的本体,因此软件的质量主要通过程序的质量体现,因此,研究一种切实可行的程序设计方法至关重要。继承是面向对象程序设计方法的一个重要标志,利用继承机制可以大大提高程序的可重用性和可扩充性。......
2023-11-07
同样,类模板不能直接使用,必须先实例化为相应的模板类,定义该模板类的对象后才能使用。程序的一次执行如下:填充一个字符数组第1个数据:a↙第2个数据:b↙第3个数据:c↙第4个数据:d↙第5个数据:e↙数组的内容是:a b c d e填充一个双精度数组第1个数据:1.2↙第2个数据:5.6↙第3个数据:3.1↙数组的内容是:1.25.63.1图5.3类模板、模板类和对象之间的关系......
2023-11-07
内联函数不能是虚函数,因为内联函数是不能在运行中动态确定其位置的。即使虚函数在类的内部定义,编译时仍将其看作是非内联的。声明虚析构函数的目的在于:使用delete运算符删除一个对象时,能确保析构函数被正确地执行。如果不相同,则被派生类虚函数的参数类型强制转换为基类中虚函数的参数类型。......
2023-11-07
声明函数模板的一般格式如下:template<模板参数表>函数返回值类型函数模板名(形参表)函数模板定义由关键字template开头,表示声明一个模板。模板参数表写在尖括号<>中,参数一般由关键字class或typename后加一个标识符构成。Class和typename的意义相同,表示后面的标识符是一个参数类型,代表一个潜在的标准类型或用户定义的类型。例如,定义max函数模板求两个数中的较大者。如下面的声明是错误的:可以看出,用函数模板比函数重载更方便,程序更简洁。......
2023-11-07
相关推荐