1、C++系统会自动把类体中的成员函数作为内置函数处理,即在程序调用这些成员函数时,并不是真正地执行函数的调用过程,而是把函数代码嵌入程序的调用点。若成员函数不在类体内定义,而在类体外定义,则系统并不将其默认为内联函数。(只有在类外定义的成员函数规模很小而调用次数很高时,才将其指定为内联函数)
2、一个对象所占的空间大小只取决于该对象中数据成员所占的空间,与成员函数无关。
3、
(1)#include<iostream>
using namespace std;
class Time
{
public:
int hour;
int minute;
int sec;
};
int main()
{
Time T1;
cin>>T1.hour>>T1.minute>>T1.sec;
cout<<T1.hour<<":"<<T1.minute<<":"<<T1.sec<<endl;
Time T2;
cin>>T2.hour>>T2.minute>>T2.sec;
cout<<T2.hour<<":"<<T2.minute<<":"<<T2.sec<<endl;
return 0;
}
(2)#include<iostream>
using namespace std;
class Time
{
public:
int hour;
int minute;
int sec;
};
int main()
{
void set_time(Time &);
void show_time(Time &);
Time T1;
set_time(T1);
show_time(T1);
Time T2;
set_time(T2);
show_time(T2);
return 0;
}
void set_Time(Time &t)
{
cin>>t.hour>>t.minute>>t.sec;
}
void show_Time(Time &t)
{
cout<<t.hour<<":"<<t.minute<<":"<<t.sec<<endl;
}
由(1)到(2),可以看出引用的妙处。
4、实现对不同的对象赋予不同的初值可采用带参数的构造函数实现。C++还提供了另一种初始化数据成员的方法—参数初始化表实现对数据成员的初始化;这种方法不在函数体内对数据成员进行初始化,而在函数首部实现。形式为:Box::Box(int h,int w):height(h),width(w){}
5、一个类只能有一个默认构造函数,为了避免调用时的歧义性;在一个类中定义了全部是默认参数的构造函数后,不能再定义重载构造函数;一个类可以有多个构造函数,但仅有一个析构函数;一般情况下,类的设计者应当在声明类的同时定义析构函数,已制定如何完成“清理”的工作,若用户没有定义析构函数,C++编译系统会自动生成一个析构函数,但它只是徒有析构函数的形式和名称,实际上什么操作也不执行。
6、对象数组:
(1) 在建立数组时,要调用构造函数,有多少个元素,调用多少次构造函数;
(2) 若构造函数有多个参数,则不能用在定义数组是直接提供所有实参的方法(编译系统只为每个对象元素的构造函数传递一个实参)
(3) 定义对象数组并初始化格式:如:
Student stud[3]={
Student(1001,18,79),
Student(1002,19,70),
Student(1003,20,98)
};
7、对象指针(对象空间的起始位置即为对象的指针):
(1) 指向对象的指针:类名 *对象指针名
(2) 指向对象数据成员的指针:数据类型名 *指针变量名
(3) 指向对象成员函数的指针:
1> 指向一般函数:数据类型名(*指针变量名)(参数表列)
2> 指向公用成员函数:数据类型名(类名::*指针变量名)(参数表列);——指针定义
指针变量名=&类名::成员函数名;——指针初始化
8、(*this).height正确;*this.height= =*( this.height)编译错误,不合法
9、共用数据的保护:
既要使数据能在一定范围内共享,又要保证它不被任意修改,此时可用const,即将有关数据定义为常量。
(1) 常对象中的数据成员为常变量且必须要有初值。如:Time const t1(12,23);
(2) 若一个对象被声明为常对象,则不能调用该对象的非const型的成员函数(除了由系统自动调用的隐式的构造函数和析构函数);有时在编程中有要求,一定要修改常对象中某个数据成员的值,可将该数据成员声明为mutable,这样就可以用声明为const的成员函数来改变它;
(3) 若将成员函数声明为常成员函数,则只能引用本类中的数据成员而不能修改它们,如:void get_time() const;
(4) 常对象只保证所有数据成员的值不被修改;若在常对象中的成员函数未加const声明,编译系统把它当做非const成员函数处理;
(5) 常成员函数不能调用另一个非const成员函数;
(6) 指向对象的常指针:将指向对象的指针变量声明为const型并将之初始化,这样指针值始终保持为其初值,不能改变;定义及初始化形式:
类名 *const指针变量名=对象地址;
(7) 指向常对象的指针变量:定义形式:const类型名 *指针变量名;若一个变量已被声明为常变量,只能用指向常变量的指针变量指向它;指向常变量的指针变量除了可以指向常变量外,还可以指向未被声明为const的变量,此时不能通过此指针变量改变该变量的值;若定义了一个指向常对象的指针变量,并使它指向一个非const的对象,则其指向的对象是不能通过指针来改变,指针变量本身的值可以改变;
10、用new动态分配内存后,将返回一个指向新对象指针的值,即所分配的内存空间的起始地址。C++允许在执行new时将新建立的对象进行初始化,如:
Box *p=new Box(12,15,18)。
11、两个同类对象之间的赋值通过赋值运算符“=”进行;对象的赋值只对其中的数据成员赋值,不对成员函数赋值;类的数据成员中不能包括动态分配的数据,否则在赋值时,可能出现严重后果。
12、对象的复制:(1)一般形式:类名对象2(对象1);表示用对象1复制对象2;(2)利用复制构造函数 (3) 类名对象2=对象1;(可实现多个对象的复制)
注:区1:对象复制和对象赋值:对象的赋值是对一个已经存在的对象赋值,因此必须先定义被赋值的对象;而对象的复制是从无到有的建立一个新对象,并使它与一个已有对象完全相同。
区2:普通构造函数和复制构造函数:(1)形式上不同:类名(形参表列);—普通构造函数的声明;类名(类名 &对象名);—复制构造函数的声明
(2)在建立对象时实参类型不同:普通构造函数实参为整型等,复制构造函数实参为对象名 (3)普通构造函数在程序中建立对象时被调用;复制构造函数在以下3种情况被调用:①程序中需要建立一个新对象,并用另一个同类的对象对其初始化②当函数的参数为类的对象时③函数的返回值是类的对象。
13、静态数据成员可以初始化,但只能在类体外进行初始化,其一般格式为:数据类型类名::静态数据成员名=初值;静态数据既可以通过对象名引用,也可以通过类名引用,静态成员函数要通过类名和域运算符“::”实现,静态成员函数的作用不是为了对象之间的沟通,而是为了能处理静态数据成员
注:静态成员函数没有this指针
14、友元(friend):
(1)friend函数可以是一般函数(非成员函数)或另一个类中的成员函数(利用提前引用声明,提前引用声明指包括类名不包括类体)
(2)友元类:在类的定义体内声明另一个类为其友元类,其生命的一般格式为
friend 类名;
(3)友元的方向是单向的而不是双向的;友元的关系不能传递。
15、类模板:如:
template<class numtype>
class Compare
{
public:
Compare(numtype a,numtype b)
{x=a;y=b;}
numtype max()
{return(x>y)?x:y;}
private:
numtype x,y;
};
声明类模板时要增加一行:
template<class 类型参数名>
用实际类型名去取代虚拟的类型,具体做法如:
Compare <int> cmpl(4,7);
上述列出的类模板中的成员函数是在类模板内定义的,若改为在类模板外定义,则类模板的形式应为如:
template<class numtype>
numtype Compare<numtype>::max()
{return(x>y)?x:y;}
模板可以有层次,一个类模板可以作为基类,派生出派生模板类。