C++ 类和对象
一、类
类(class)是面向对象程序设计的最基本的概念,是C++最强有力的特征,是进行封装和数据隐藏的工具,它将一个数据结构与一个操作集紧密地结合起来。类对象是类的实例,用类对象模拟现实世界中的事物比用数据对象更确切。
1.类与结构体
结构体是C的一种自定义的数据类型,它把相关联的数据元素组成一个单独的统一体。
有关日期结构的例子
#include <iostream> struct Date { int year; int month; int day; }; int main() { Date date1; date1.year=2003; date1.month=8; date1.day=25; cout<<date1.year<<"."<<date1.month<<"."<<date1.day<<endl; return 0; }
class与struct的比较
- 类是C++对C中结构体的扩展。
- C语言中的struct是数据成员集合,而C++中的类,则是数据成员和成员函数的集合。
- 构造数据类型:c++和struct都是用户定义的数据类型,是一种构造数据类型。
- C结构无法对数据进行保护和权限控制,所以结构中的数据是不安全的。C++中的类将数据和与之相关联的数据封装在一起,形成一个整体,具有良好的外部接口可以防止数据未经授权的访问,提供了模块间的独立性。
2 类的构成
类的成员分两部分:一部分对应数据的状态,称为数据成员,另一部分为作用于该数据状态的函数,称为成员函数。
类声明的一般格式如下:
class 类名 { public: 公有数据成员; 公有成员函数; protected: 保护数据成员; 保护成员函数; private: 私有数据成员; 私有成员函数; };
3个关键字: private
、protected
和public
,称为访问权限关键字。每个关键字下面又都可以有数据成员和成员函数。
private
部分称为类的私有部分,这一部分的数据成员和成员函数称为类的私有成员。私有成员只能由本类的成员函数访问,而类外部的任何访问都是非法的。public
部分称为类的公有部分,这部分的数据成员和成员函数称为类的公有成员。公有成员可以由程序中的函数访问,它对外是完全开放的。protected
部分称为类的保护部分,这部分的数据成员和成员函数称为类的保护成员。保护成员可以由本类的成员函数访问,也可以由本类的派生类的成员函数访问,而类外的任何访问都是非法的。
注意:
- (1) 类声明格式中的3个部分并非一定要全有,但至少要有其中的一个部分。
- 一般一个类的数据成员应该声明为私有成员,成员函数声明为公有成员。
- (2) 类声明中的
private
、protected
和public
三个关键字可以按任意顺序出现任意次。 - (3)
private
处于类体中第一部分时, 关键字private
可以省略。 - (4) 数据成员可以是任何数据类型,但不能用自动(auto)、寄存器(register)或外部(extern)进行声明。
- (5) 不能在类声明中给数据成员赋值。C++规定,只有在类对象定义之后才能给数据成员赋初值
用一个类来描述日期,其形式如下:
class Date { public: void setDate(int y,int m,int d); void showDate(); private: int m_year; int m_month; int m_day; };
3. 成员函数的声明
成员函数的声明通常采用内联函数和外联函数两种方式:
1) 内联函数
- 内联函数是指那些定义在类体内的成员函数,即该函数的函数体放在类体内。
- 内联函数在调用时不是像一般函数那样要转去执行被调用函数的函数体,执行完成后再转回调用函数中,执行其后语句,而是在调用函数处用内联函数体的代码来替换,这样将会节省调用开销,提高运行速度。
- 内联函数与带参数的宏定义进行一下比较,它们的代码效率是一样的,但是内联函数要优于宏定义,因为内联函数遵循函数的类型和作用域规则,它与一般函数更相近,在一些编译器中,一旦关上内联扩展,将与一般函数一样进行调用,调试比较方便。
内联函数声明的形式如下
class Date { public: void setDate(int y,int m,int d){ m_year=y;m_month=m;m_day=d; }; void showDate(); private: int m_year; int m_month; int m_day; };
2) 外联函数
即在类的声明中只给出成员函数的原型,而成员函数体写在类的外部。外联函数变成内联函数的方法很简单,只要在函数头前面加上关键字inline就可以了。通常只有较短的成员函数才定义为内联函数,对较长的成员函数最好作为外联函数处理。
外联函数声明形式:
返回类型 成员函数 (参数列表); 类外定义的一般形式是: 返回类型 类名∷成员函数名(参数表) { // 函数体 }
例如, 以下是表示日期类内声明,类外完成函数体。
class Date { public: void setDate(int y,int m,int d); void showDate(); private: int m_year; int m_month; int m_day; }; void Date::setDate(int y, int m, int d) { m_year=y;m_month=m;m_day=d; }
外联函数转化为内联函数:
class Date { public: void setDate(int y,int m,int d); void showDate(); private: int m_year; int m_month; int m_day; }; inline void Date::setDate(int y, int m, int d) { m_year=y;m_month=m;m_day=d; }
二、对象
1. 对象的定义和使用
1)类与对象的关系
通常我们把具有共同属性和行为的事物所构成的集合叫做类。
在C++中,可以把相同数据结构和相同操作集的对象看成属于同一类。
在C++中,类也是一种用户自定义数据类型,类的对象可以看成是该类类型的一个实例,定义一个对象和定义一个变量相似。类与对象间的关系,可以用数据类型int和整型变量i之间的关系类比。
C++把类的变量叫做类的对象,对象也称为类的实例。
2)对象的定义
对象的定义, 也称对象的创建。
在C++中可以用以下两种方法定义对象:
(1) 在声明类的同时,直接定义对象。
class Date { public: void setDate(int y,int m,int d); void showDate(); private: int m_year; int m_month; int m_day; }date1,date2;//创建对象date1和date2
(2) 声明了类之后,在使用时再定义对象
class Date { public: void setDate(int y,int m,int d) { m_year=y;m_month=m;m_day=d; }; void showDate(); private: int m_year; int m_month; int m_day; }; int main(){ Date date1,date2; return 0; }
说明:
- 在声明类的同时定义的对象是一种全局对象,在它的生存期内任何函数都可以使用它。
- 声明了一个类便声明了一种类型,它并不接收和存储具体的值,只作为生成具体对象的一种“样板”,只有定义了对象后,系统才为对象分配存储空间。
3) 对象中成员的访问
有两种访问方式:.和->
(1)普通对象,使用操作符“.”
当定义了一个类的对象后,就可以访问对象的成员了。在类的外部可以通过类的对象对公有成员进行访问,访问对象成员要使用操作符“.”。
访问的一般形式是:
- 对象名.数据成员名
- 对象名.成员函数名(参数表)
其中“.”叫做对象选择符,简称点运算符。
使用类Date的完整程序
#include <iostream> using namespace std; class Date { public: Date(){}; void setDate(int y,int m,int d) { m_year=y;m_month=m;m_day=d; }; void showDate(){ cout<<"year:"<<m_year<<", mouth:"<<m_month<<", day:"<<m_day<<endl; }; private: int m_year; int m_month; int m_day; }; int main(){ Date date1;//创建对象 date1.setDate(2020,2,10);//访问对象的成员函数 date1.showDate(); return 0; }
说明:
- 在类的内部所有成员之间都可以通过成员函数直接访问,但是类的外部不能访问对象的私有成员。
一个存在错误的程序:不可直接在类外部访问类的私有成员
#include <iostream> using namespace std; class Date { public: Date(){}; void setDate(int y,int m,int d) { m_year=y;m_month=m;m_day=d; }; void showDate(){ cout<<"year:"<<m_year<<", mouth:"<<m_month<<", day:"<<m_day<<endl; }; private: int m_year; int m_month; int m_day; }; int main(){ Date date1;//创建对象 date1.setDate(2020,2,10);//访问对象的成员函数 date1.showDate(); cout<<date1.m_year;//错误,不可访问类的私有成员 return 0; }
(2)指针类对象
在定义对象时,若定义的是指向对象的指针,则访问此对象的成员时,要用“->”操作符。
#include <iostream> using namespace std; class Date { public: Date(){}; void setDate(int y,int m,int d) { m_year=y;m_month=m;m_day=d; }; void showDate(){ cout<<"year:"<<m_year<<", mouth:"<<m_month<<", day:"<<m_day<<endl; }; private: int m_year; int m_month; int m_day; }; int main(){ Date *date1=new Date();//创建对象 date1->setDate(2020,2,10);//访问对象的成员函数 date1->showDate();//year:2020, mouth:2, day:10 return 0; }
2. 类成员的访问属性
类成员有三种访问属性:公有(public)、 私有(private) 和保护(protected) 。
- 说明为公有的成员不但可以被类中成员函数访问;还可在类的外部,通过类的对象进行访问。
- 说明为私有的成员只能被类中成员函数访问,不能在类的外部,通过类的对象进行访问。
- 说明为保护的成员除了类本身的成员函数可以访问外,该类的派生类的成员也可以访问,但不能在类的外部,通过类的对象进行访问。类成员的访问属性
类的成员对类对象的可见性和对类的成员函数的可见性是不同的。
类的成员函数可以访问类的所有成员,而类的对象对类的成员的访问是受类成员的访问属性的制约的。
3. 类中成员的访问方式
- 类中成员互访:直接使用成员名
- 类外访问:使用“对象名.成员名”方式访问 public 属性的成员
#include <iostream> using namespace std; class Date { public: Date(){}; void setDate(int y,int m,int d) { m_year=y;m_month=m;m_day=d; }; void showDate(){ cout<<"year:"<<m_year<<", mouth:"<<m_month<<", day:"<<m_day<<endl; }; private: int m_year; int m_month; public: int m_day; }; int main(){ Date date1;//创建对象 date1.setDate(2020,2,10);//访问对象的成员函数 date1.showDate();//year:2020, mouth:2, day:10 date1.m_day=20;//合法访问方式,因为m_day是public成员 date1.m_mouth=3; //非法访问方式,因为m_mouth是private成员 date1.showDate();//year:2020, mouth:2, day:20 return 0; }
一般来说,公有成员是类的对外接口,而私有成员和保护成员是类的内部数据和内部实现,不希望外界访问。
将类的成员划分为不同的访问级别有两个好处:一是信息隐蔽,即实现封装;二是数据保护,即将类的重要信息保护起来,以免其它程序不恰当地修改。
3.6 类的作用域
所谓类的作用域就是指在类声明中的一对花括号所形成的作用域。
- 一个类的所有成员都在该类的作用域内,一个类的任何成员可以访问该类的其他成员。
- 一个类的成员函数可以不受限制地访问类的成员,而在类的外部,对该类的数据成员和成员函数的访问则要受到一定的限制,有时甚至是不允许的,这体现了类的封装功能。
理解类的作用域
#include <iostream> using namespace std; class Date { public: Date(){}; void setDate(int y,int m,int d) { m_year=y;m_month=m;m_day=d; }; void showDate(){ cout<<"year:"<<m_year<<", mouth:"<<m_month<<", day:"<<m_day<<endl;//可以访问类中数据成员 }; private: int m_year; int m_month; public: int m_day; }; int main(){ Date date1;//创建对象 date1.setDate(2020,2,10);//访问对象的成员函数 date1.showDate();//year:2020, mouth:2, day:10 m_day=20;//非法,不能直接访问类中的m_day,可改写成date1.m_day=20 date1.m_day=20; date1.showDate();//year:2020, mouth:2, day:20 return 0; }
参考自:https://www.cnblogs.com/whale90830/p/10520364.html