1:类和对象的基础知识
(1)类的定义:
类(Class)实际上是对某种类型的对象变量和方法的原型.类是从一些具有相同属性或功能的具体实例,抽象出共有的一些属性的,自定义抽象数据类型。
(2)类的三大特性:
封装性:也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。
继承性:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。
多态性:是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。
实现多态,有二种方式,覆盖,重载。
覆盖,是指子类重新定义父类的虚函数的做法。
重载,是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。
(3)访问限定符:
1.Public(公有的):访问不受限制。
2.Protected(保护)访问范围限定 于它所属的类 或从该 类派生 的类型。
3.Private(私有的)访问范围限定于它所属的类型。
注意:
1. public成员可从类外部直接访问,private/protected成员不能从类外部直接访问。
2. 每个限定符在类体中可使用多次,它的作用域是从该限定符出现开始到下一个限定符之前或类体结束前。
3. 类体中如果没有定义限定符,则默认为私有的。
4. 类的访问限定符体现了面向对象的封装性。
(4) 类的作用域:类的作用域简称类域,它是指在类的定义中由一对花括号所括起来的部分,每一个类都具有该类的类域,该类的成员局部于该类所属的类域中。
对象可以通过 . 直接访问公有成员,指向对象的指针通过-> 也可以直接访问对象的公有成员。
在类体外定义成员,需要使用 :: 作用域解析符指明成员属于哪个类域
//用 .访问
Person p1;
p1._name = "peter";
p1._age = 18;
p1._sex = "男";
p1._id = 0;
//用指针和->访问
p1.Display();
Person* ptr1 = &p1;
ptr1->Display();
(6)类实例对象
1)在面向对象的编程中,通常把用类创建对象的过程称为实例化,其格式如下:类名 对象名 = new 类名(参数1,参数2...参数n)(这里,“类名”这个类名实例化成了“对象名”这个对象)如 Date *date=new Date();就是用日期类创建了一个日期的对象,就叫对象的实例化。
2)注意:类对象存储模型中每个对象的 大小为类中所有成员变量大小之和,遵从内存对齐原则 。
3)内存对齐原则 (结构体内存对其规则):
1.第一个成员在与结构体变量偏移量为0的地址处。
2.其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。//对齐数 =编译器默认的一个对齐数与该成员大小的较小值。VS中默认的值为8 gcc中的默认值为4
3.结构体总大小为最大对齐数(每个成员变量除了第一个成员都有一个对齐数)的整数倍。
4.如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
5,优点:提高效率(浪费空间,以空间换时间)
Class A
{
char ch;
double d;
}
//windows:sizeof(A)=8+8=16
linux: sizeof(A)=4+8=12
2.四个默认成员函数及运算符重载相关知识
类的六个默认成员函数:构造函数,拷贝构造,析构函数,赋值运算符的重载,取地址操作符重载,Const修饰的取地址操作符重载。
(1)构造函数;成员变量为私有的,要对它们进行初始化,必须用一个公有成员函数来进行。同时这个函数应该有且仅在定义对象时自动执行一次,这时调用的函数称为构造函数(constructor)。构造函数是特殊的成员函数。
特征1. 函数名与类名相同。2. 无返回值。3. 对象构造(对象实例化)时系统自动调用对应的构造函数。4. 构造函数可以重载。5. 构造函数可以在类中定义,也可以在类外定义。6. 如果类定义中没有给出构造函数,则C++编译器自动产生一个缺省的构造函数,但只要我们定义了一个构造函数,系统就不会自动生成缺省的构造函数。7. 无参的构造函数和全缺省值的构造函数都认为是缺省构造函数,并且缺省的构造函数只能有一个。
Date (int year=2017,int month=6,int day=28) //全缺省构造函数
{
}
Date() //无参构造函数
{
}
(2)拷贝构造:创建对象时使用同类对象来进行初始化,这时所用的构造函数称为拷贝构造函数(Copy Constructor),拷贝构造函数是特殊的构造函数。
特征:1. 拷贝构造函数其实是一个构造函数的重载。
2. 拷贝构造函数的参数必须使用引用传参,使用传值方式会引发无穷递归调用。
3. 若未显示定义,系统会默认缺省的拷贝构造函数。缺省的拷贝构造函数会,依次拷贝类成员进行初始化。
Date d2(d1) //通过d1拷贝构造 d2
d2.Displaay();
(3)析构函数 :当一个对象的生命周期结束时,C++编译系统会自动调用一个成员函数,这个特殊的成员函数即析构函数(destructor)构造函数是特殊的成员函数,其特征如下:
1. 析构函数在类名加上字符~。
2. 析构函数无参数无返回值。
3. 一个类有且只有一个析构函数。若未显示定义,系统会自动生成缺省的析构函数。
4. 对象生命周期结束时,C++编译系统系统自动调用析构函数。
注意析构函数体内并不是删除对象,而是做一些清理工作。
Class Seplist
{
Public:
seqlist()
{
/*_array=NULL;
_size_0;
_capacity=0;*/
_array=(int*)malloc(Sizeof(int)*3);
_size=0;
_capacity=0;
}
void Pushback(int x)
{
//check Capacity;
_array[_size]=x;
_size++;
}
~Seqlist()//析构函数
{
free(_array);
_size=_Capacity=0;
}
int main()
{
Seqlist S1;
return 0;
}
}
(4)运算符重载
1)运算符重载,就是对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型,
2)特征:operator+合法的运算符 构成函数名 (重载<运算符的函数名:operator<).
3)注意; ,*/::/sizeof/?:/,这五种不能重载,
(5)赋值运算符重载
1)即对一个已经存在的对象进行拷贝复制
Date d1(d2);//拷贝构造(d1不存在,用d2去构造d1)
d1=d2;//赋值运算符重载(d1d2都存在,仅赋值)
3.隐含的this指针等,
1). 每个成员函数都有一个指针形参,它的名字是固定的,称为this指针,this指针是隐式的。(构造函数比较特殊,没有这个隐含this形参)
2). 编译器会对成员函数进行处理,在对象调用成员函数时,对象地址作实参传递给成员函数的第一个形参this指针。
3). this指针是成员函数隐含指针形参,是编译器自己处理的,我们不能在成员函数的形参中添加this指针的参数定义,也不能在调用时显示传递对象的地址给this指针。
void Display ()
{
cout<<_year<<endl;
}
//编译器处理添加this指针
void Display (Date* this ) { cout<<this->_year<<endl; }