C++入门知识(2):
1:类和对象:
类(class):
类的定义:类(class)实际上是一种高度抽象化的东西,百度上对类的定义是:类的实质是一种数据类型,类似于int、char等基本类型,不同的是它是一种复杂的数据类型。因为它的本质是类型,而不是数据,所以不存在于内存中,不能被直接操作,只有被实例化为对象时,才会变得可操作。简单来说:它们是一些具有共同特征的事物的集合。类是具有相同属性和服务的一组对象的集合。
例如,我们可以定义一个学生类:
class
{
public :
void print()
{
cout<<"hehe"<<endl;
}
private:
int age;
char* name;
char* sex;
};
类里面包括,成员变量和成员函数。
面向对象的三大特征:封装,继承,多态。
封装是面向对象程序设计的一个重要原则。它有两方面涵义,第一个涵义是,把对象的全部属性和全部服务结合在一起,形成一个不可分割的独立单位(对象)。第二个涵义也称做“信息隐蔽”,即尽可能隐蔽对象的内部细节,对外形成一个边界,保留有限的接口使之与外界发生联系。
用比较简洁的语言给出封装的定义:封装就是把对象的属性和服务结合成一个独立系统单位,并尽可能的隐藏对象的内部细节。
继承和多态会在以后的博客中进行解释。
类有三种基本的访问限定符:
(1)公有成员访问限定符(public):既可以被本类中的成员函数访问,也可以被类的作用域外的其他函数和类访问。
(2)私有成员访问限定符(private):成员只能被该类中的成员函数访问,类外的其他函数则不能(友元类除外)
(3)保护成员访问限定符(protected):成员只能被该类的成员函数或派生类的成员函数访问。
它们的作用域都是从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
类的默认访问限定符是private。
对象:
前面说过,类是很多具有相同属性和服务的对象的集合,换而言之,对象是类的实例化。
一个类可以实例化很多对象。
对象的大小是类中所有成员变量的大小之和,不是单纯的相加,这里遵循内存对齐原则。
#include <iostream>
using namespace std;
class Date
{
public:
Date(int year,int month,int day)
{
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d(2017,6,30);
return 0;
}
上面这个程序里的 d 就是Date类的一个实例化对象。
四个默认成员函数及运算符重载
C++里一共有六个默认成员函数,这里介绍一下四个比较常用的默认成员函数。
默认成员函数:
(1):构造函数
构造函数时用来初始化一个对象的,当对象被创建时, 构造函数自动被调用。其名字与类名相同,在对象的生命周期内调用且只调用一次,以保证每个数据成员都有一个合适的初始值。
特点:
(1):构造函数的函数名类名相同;
(2):无返回值;
(3):支持重载,可以自己定义构造函数,实参决定了调用哪个构造函数;
(4):实际上在执行构造函数里面的内容时,会先执行初始化列表;
(5):构造函数只在创建对象时有用,一个对象只能调用一次;
(6):如果不自己显示定义构造函数,那么编译器会提供一个无参的默认构造函数;
(7):缺省构造函数只能有一个;
例如下面这个例子,我们自己定义了一个构造函数:
#include <iostream>
using namespace std;
class Date
{
public:
Date(int year,int month,int day)//构造函数
{
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d(2017,6,30);
return 0;
}
拷贝构造函数 :
拷贝构造函数与构造函数是重载关系;函数的返回值和函数名都和构造函数的相同,唯一不同的就是参数,拷贝构造的参数是一个已经存在的对象。参数常用 const 修饰。拷贝构造函数是特殊的构造函数,创建对象时使用已存在的同类对象来进行初始化。
例如:
class Date
{
public:
Date(int year,int month,int day)
{
_year = year;
_month = month;
_day = day;
}
Date(const Date& date)//一定要写成引用
{
_year = date._year;
_month = date._month;
_day = date._day;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1(2017,6,30);
Date d2(d1);//用已经存在的对象d1来初始化d2对象;
return 0;
}
*注意:拷贝构造函数的形参一定要写成引用,不然程序会崩溃,因为它会不断调用拷贝构造函数,会造成死循环。*
如果函数的参数是传值方式或者函数有返回值,都会去调用拷贝构造函数。
析构函数:
在一个对象的生命周期结束时,也就是这个对象被销毁时,析构函数会完成一些清理工作。
特点:
(1):函数名是 ~类名,无参数,无返回值;
(2):对象生命周期结束时,C++编译系统系统自动调用析构函数。
(3): 如果不显示定义,编译器会生成一个默认的析构函数。
#include <iostream>
using namespace std;
class A
{
public:
~A()
{
cout<<"hehe"<<endl;
}
A(int a)
{
_a = a;
}
private:
int _a;
};
int main()
{
A a(1);
return 0;
}
该程序它会输出一句 hehe ,因为调用了析构函数。
赋值运算符的重载:
#include <iostream>
using namespace std;
class A
{
public:
A(int a)
{
_a = a;
}
A operator=(const A& B)
{
_a = B._a;
return *this;
}
private:
int _a;
};
int main()
{
A a(1);
A b(2);
a = b;//将b赋给a
return 0;
}
用于对象之间的赋值;operator是运算符重载的一个关键字。
隐含的this指针:
this作用域是在类内部,当在类的非静态成员函数中访问类的非静态成员的时候,编译器会自动将对象本身的地址作为一个隐含参数传递给函数。也就是说,即使你没有写上this指针,编译器在编译的时候也是加上this的,它作为非静态成员函数的隐含形参,对各成员的访问均通过this进行。
this指针指向当前对象;
例如:
#include <iostream>
using namespace std;
class Date
{
public:
Date(int year,int month,int day)//构造函数
{
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d(2017,6,30);
return 0;
}
这个程序中,在调用构造函数时,会传一个this指针,该指针指向当前的对象。直观的来写就是:
Date(int year,int month,int day)
{
this->_year = year;
this->_month = month;
this->_day = day;
}
而我们平时会省略this ,当时实际上他是存在的。
又例如,在调用赋值运算符时
A operator=(const A& B)
{
_a = B._a;
return *this;
}
A a(1);
A b(2);
a = b;
a = b 实际上就是
a.operator(&a,b);
A operator=(const A& B)
{
this->_a = B._a;
return *this;
}