内容发布更新时间 : 2024/12/26 10:04:08星期一 下面是文章的全部内容请认真阅读。
类和对象初步
1. 类的定义在定义外成员函数的实现
2. 类的成员函数之间可以相互调用,类的成员函数也可以重载,也可设默认参数值
3. 一般来讲,一个对象占用的内存空间的大小等于其成员变量的体积之和。每个对象都有自己的存储
空间(成员变量),但成员函数只有一份对象名.成员名指针->成员名引用名.成员名 4. private:一个类的私有成员,只能在该类的成员函数中才能访问 public: proteced: 5. class默认 private struct默认public
6. 内联成员函数:成员函数名前加inline 或函数体写在类定义内部的成员函数。执行更快,但会带来
额外的内存开销
构造函数
1. 构造函数全局变量在堆上,系统自动初始化为零。局部变量在栈上,初始值是随机的,需要初始化。 2. 构造函数:对对象进行初始化。构造函数执行时对象的内存空间已经分配,构造函数的作用是初始
化这片空间。可重载,不写的话有默认构造函数,但是如果编写了构造函数,那默认构造函数不会再执行。是一类特殊的成员函数。不写返回值类型,函数名为类名。 3. 对象在生成时一定会调用某个构造函数,一旦生成,不再执行构造函数。 4. P183 Ctest *pArray[3]={new Ctest(4),new Ctest(1,2)}
5. 复制构造函数:其是构造函数的一种,只有一个参数,为本类的引用,防止混淆,构造函数不能以
本类的对象作为唯一的参数。默认复制构造函数。
6. 复制构造函数被调用的三种情形:1用一个对象去初始化另一个对象时Complex C1(C2) Complex
C2=C1; 2 函数的参数是类A的对象。形参未必等于实参函数中用对象的引用不会调用复制构造函数 void Function(const Complex &c)3 函数的返回值是类A的对象
7. 类型转换构造函数:除复制构造函数外,只有一个参数的构造函数 C=6
8. 析构函数:在对象消亡时调用,可以定义其做善后工作。是一类特殊的成员函数,一个类有且只有
一个构造函数。默认析构函数
9. 注意:函数的参数对象以及作为函数返回值的对象,在消亡时也会调用析构函数
10. 构造函数析构函数变量的生存期:全局变量在main函数开始执行前初始化。函数调用结束后静态局
部对象不消亡。main函数结束时,静态局部对象先消亡,全局对象再消亡
11. 静态成员变量和静态成员函数:实质是全局变量和全局函数,被所有的同类共享。生成在对象生
成之前。计算体积时不会将静态成员变量算入其中老师的coeblocks C0 13 静态成员变量必须在类定义外进行声明,声明的同时也可初始化。因为静态成员函数内部不作用于某个对象,所以不能访问非静态成员
12. 常量对象和常量成员函数:常量对象一旦初始化后,值再也不能改变。常量对象和普通对象都可
调用常量成员函数。通过常量对象调用常量成员函数。常量成员函数内不能调用同类的非常量成员函数,静态成员函数除外。
13. 封闭类:包含成员对象的类。在定义封闭类的构造函数时,用初始化列表的方式初始化。封闭类
对象生成时,先执行所有成员对象
友元和this
1. 友元函数:把全局函数和其它类的成员函数声明为友元函数后,可直接在友元函数内部访问该类的私
2. 3. 4. 5. 6.
7.
运算符重载
1. 运算符重载:是对已有的运算符赋予多重含义,使不同的运算符作用于不同的类型的数据时导致的
不同的行为。实质是编写运算符作为名称的函数。 2. 返回值类型 operator 运算符(形参表){......}
3. 使用了被重载的运算的表达式,会被编译成对运算符函数的调用,实参是运算符的·操作数,运算的
结果是函数的返回值。运算符可多次被重载,可重载为全局函数和成员函数。重载为全局函数时,参数个数等于操作符的个数;重载为成员函数时,参数的个数等于操作数的个数减1. a—b被重载为a.operator-(b);
4. 类名(构造函数参数表)这个写法表示生成一个临时对象。该临时对象没有名字,生存期到包含它
的语句执行完为止。
5. C++规定 = 只能重载为成员函数.赋值运算符可以连用。
6. const char *c_str() const {return str); 两种错误的情形: char *p=s.c_str(); strcpy(s.c_str(),\7. a=b=\等价于a.operator=(b.operator=(\8. (a=b)=c;等价于(a.operator=(b)).operator=(c);
9. 深复制和浅复制:两个对象的指针成员变量指向同一个地方,指向两个不同的地方。 10. 将运算符重载为友元函数
11. 重载插入运算符和流提取运算符:cout是ostream类的对象。ostream类和cout都是在iostream头文
件中声明的。ostream类将\多次重载为成员函数。比如:ostream&ostream::operator<<( const char*s) {... return *this;) ostream&ostream::operator<<(int n) {... return *this;)
12. 返回值*this是cout的引用cout<<\等价于(cout.operator<<(\13. 重载强制类型转换运算符:(类型名)对象等价于对象.operator 类型名() 14. 重载自增,自减运算符obj++ CDemo operator++(int) 15. ++objCDemo operator++(int)
继承与派生
1. 继承与派生的关系:A类派生出B类,B类继承了A。派生类是通过对基类进行扩充和修改后得到
的。基类所有成员自动成为派生类成员。在派生类的成员函数中,不能访问基类的私有成员。派生类对象的体积等于基类对象的体积加上自己成员变量的体积。在派生类对象中,包含着基类对象,且基类对象的存储位置位于新增的成员变量之前。
2. 基类的构造函数和析构函数不能被派生类继承,需要自己重新定义。如果基类构造函数没有定义,
派生类也可不定义,用缺省。如果基类的构造函数定义,派生类构造函数一定要定义。
3. 注意:在基类和派生类中有同名成员,在派生类成员函数或派生类对象中访问同名成员,除非特别
之指出,访问的是派生类的成员。以下两种情况访问的是基类的成员:s2.CStudent::PrintInfo(); p->CStudent::PrintInfo();
4. 复合关系和继承关系:复合关系,有,表现为封闭类,但不一定只是封闭类。即一个类以另一个类
的对象作为成员变量。继承关系,是,类B继承类A,满足B所代表的事物也是A所代表的事物 5. 类A知道类B:类A的成员变量是类B的指针 6. ////////导出类构造函数和析构函数的构建
基类的构造函数和析构函数不能被派生类继承。
如果基类没有定义构造函数,派生类也可以不定义构造函数,全都采用缺省的构造函数,此时,派生类新增成员的初始化工作可用其他公有函数来完成。
如果基类定义了带有形参表的构造函数,派生类就必须定义构造函数,提供一个将参数传递给基类
有成员;但不能把其它类的私有成员函数声明为友元。
全局函数声明为友元:friend 返回值类型函数名(参数表);
其它类的成员函数声明为友元:friend 返回值类型其它类的类名::成员函数名(参数表); 友元类:类A将类B声明为自己的友元,则类B中所有的成员函数都可访问类A对象中的私有成员。私有成员函数也可访问。 注意:友元关系不能传递。
this指针:非静态成员函数的实际形参比编写的多一个,就是this指针,指向成员函数作用的对象。通过this指针找到对象所在的地址,继而找到对象非静态成员变量的地址。
注意:因为静态成员函数不作用于某个对象,所以在其内部无this指针,不能使用。
构造函数的途径,以便保证在基类进行初始化时能获得必需的数据。
如果派生类的基类也是派生类,则每个派生类只需负责其直接基类的构造,不负责自己的间接基类的构造。
派生类是否要定义析构函数与所属的基类无关,如果派生类对象在撤销时需要做清理善后工作,就需要定义新的析构函数。
多态与虚函数
1. 多态:派生类对象的地址可以赋值给基类指针。对于通过基类指针调用基类和派生类中都有的同名
的,同参数的虚函数的语句,编译时不需要确定执行的是基类的还是派生类的虚函数。当程序运行到该语句时,如果基类指针指向的是一个基类对象,则调用基类的虚函数;如果基类指向的是一个派生类对象,则调用派生类的虚函数。这种机制成为多态;
2. 面向对象程序设计语言有封装,继承,多态三种机制,这三种机制能够有效提高程序的可读性,可
扩充性和可重用性。
3. 多态指同一事物可以完成不同的功能。分为编译时的多态和运行时的多态。前者主要指函数的重载
(包括运算符重载),对重载函数的调用。后者主要与继承,虚函数等概念有关。
4. 虚函数:声明前面加了virtual关键字的成员函数。virtual 关键字只能在类定义中的成员函数声明处
使用,不能在类外编写成员函数体时使用。静态成员函数不能是虚函数。包含虚函数的类成为多态类。
5. 多态可以简单地理解成同一条函数调用语句能调用不同的函数。或者对不同的对象发同一消息,使
得不同对象有各自不同的行为。
6. 注意:多态的语句调用的是哪个类的成员函数,是在运行时才能确定的,编译时不能确定。因此多
态的函数调用语句是动态联编的,普通的函数调用语句时静态联编的。
7. 通过基类引用实现多态。通过基类的引用调用虚函数的语句是多态的,即通过基类的引用调用基类
和派生类中的同名同参表的虚函数时引用的是哪个类的对象,调用该对象的虚函数。
8. 多态的实现原理:每一个有虚函数的类,都有一个虚函数表,列出了该类所有虚函数的地址。该类
的任何对象都存放着该虚函数表的指针。位于对象存储空间的最前端,在数据成员之前,里面存放着虚函数表的地址。
9. 多态的实现过程:根据基类指针所指向的或基类引用所引用的对象中存放的虚函数表的地址,查找
要调用的虚函数的地址,调用虚函数。
10. 类的成员函数可以相互调用,在成员函数(静态,构造,析构除外)中调用同类的虚函数的语句是
多态的。
11. 在构造函数和析构函数中调用虚函数不是多态的,即编译时即可确定。如果本类有该函数,则调用
本类的,本类没有调用直接基类的,基类没有,调用间接基类的。。。
12. 注意:只要在基类中某个函数被声明为虚函数,则在直接和间接派生类中,同名同参数的成员函数
即使不写virtual也自动成为虚函数。
13. 虚析构函数:如果一个基类指针指向new出来派生类的对象,释放该对象时是通过该基类指针来完
成的。
14. 如果基类的析构函数是虚函数,派生类的析构函数即使不用virtual关键字也自动成为虚函数。 15. 注意:!!析构函数可以是虚函数,但构造函数不可以! 16. 纯虚函数:没有函数体的虚函数;在函数声明后加=0;
17. 抽象类:包含纯虚函数的类;不能生成独立的对象,但抽象类可以作为基类,派生出新类。因此,
独立的抽象类的对象不存在,但是被包含在派生类对象中的抽象类的对象,是可以存在的(但要实例化,有函数体)。
18. 可以定义抽象类的指针或引用,让他们指向或引用抽象类的派生类的对象,实现多态。
19. 如果一个类从抽象类派生而来,那么当且仅当它对基类中所有纯虚函数都进行覆盖并都写出函数体
({}也是),它才能成为非抽象类。
函数调用也会带来降低效率的问题,因为调用函数实际上将程序执行顺序转移到函数所存放在内存中某个地址,将函数的程序内容执行完后,再返回到转去执行该函数前的地方。这种转移操作要求在转去前要保护现场并记忆执行的地址,转回后先要恢复现场,并按原来保存地址继续执行。
因此,函数调用要有一定的时间和空间方面的开销,于是将影响其效率。特别是对于一些函数体代码不是