从今天开始,我们将要接触到c++最主要的内容:面向对象编程。
面向对象编程有以下几个特性:
抽象:将现实中的事物抽象成类和对象
封装和数据隐藏:将我们使用的数据封装到类中,我们可以设置哪些数据不能被外界访问。
继承、多态:在原有类的基础上,创建新的类,根据传入对象类型的不同,执行不同的操作。
创建自己的类,类包含以下两个部分:
类声明:以数据成员的方式描述数据部分,以成员函数的方式描述公共接口。提供类的蓝图
类方法定义:实现类的成员函数。
我们将类的声明放在头文件中,类方法定义放在源文件中,在源文件引入类声明的头文件。如Time.h:
#ifndef TIME_H_
#define TIME_H_
class Time {
private :
int hour ;
int minute ;
int second ;
public :
void setTime(int h , int m , int s) ;
int getHour(){
return hour ;
}
int getMinute(){
return minute ;
}
int getSecond(){
return minute ;
}
void setHour(int h) {
hour = h ;
}
void setMinute(int m ){
this->minute = m ;
}
void setSecond(int s){
this->second = s ;
}
void print() ;
} ;
#endif
Time.h使用#ifndef #define #endif 条件预编译指令,这样可以在多个源文件中包含该类的定义,而不会出现定义多次。
private: 标示数据是私有成员,外界不能访问,只有本类的成员函数能够使用,public:公有成员,提供外界访问的接口,还有protected,在继承时在讲解。这三个访问控制符。
声明了Time类,在类内部实现的函数默认是内联函数,也可以不再内部实现,只在实现前加inline也可成为内联函数。如:inline void Time::print() {}
在类外实现函数时,要加上Time:: 如:
void Time::setTime(int h , int m , int s ) {
hour = h ;
minute = m ;
second = s ;
}
函数内也是类的作用域中,可以直接使用数据成员,外部不再类的作用域中,要加上Time::作用域解析符 标示函数所属类。
数据成员可以是基本类型、复合类型、指针、引用等,不能使用Time类型成员,但可以使用Time指针 或引用。
#include"Time.h" //引用自定义头文件 "Time.h" 双引号
#include<iostream> //引用标准头文件
void Time::setTime(int h ,int m , int s ) { //Time::
hour = h ;
minute = m ;
second = s ;
}
void Time::print(){
using namespace std ;
cout << "Hour : " << hour << " ,Minute : " << minute << " ,Second : " << second << endl ;
}
则已经创建了Time类型,我们就可以使用Time来创建自己的对象了。
#include "Time.h"
#include<iostream>
int main(){
Time t ; //使用默认构造函数创建对象t
t.setTime(12, 30 , 45) ; //调用成员函数
t.print() ;
Time *pt = new Time() ;
pt->setTime(10, 20 , 30) ; //指针调用成员函数
pt->print() ;
delete pt ;
return 0 ;
}
类提供了一个特殊的函数:构造函数,用来创建对象,并 把值赋给数据成员,若自己没有定义,则系统会提供默认构造函数,什么也不执行。
构造函数没有返回值,函数名跟类同名:
//Time.h 声明
Time(int h , int m = 0 ,int s = 0) ; //可以使用默认参数
//Time.cpp
Time::Time(int h , int m , int s ) {
hour = h ;
minute = m ;
second = s ;
}
//main.cpp
Time t = Time(12 ,23 , 34) ; // xian xing diao yong gou zao han shu
Time t2(7 , 23 , 34 ) ; //yin xing diao yong gou zao han shu
当我们自己创建了构造函数后,系统就不再提供默认构造函数Time() ; 了,我们必须使用上面两种方式创建对象,我们也可以通过函数重载定义默认构造函数,即无参构造函数或提供所有默认值的函数。因为有好多地方要用到默认构造函数,所以我们尽量要提供一个。
析构函数:当用构造函数创建对象后,程序就会跟踪所创建的对象,直到该对象过期,则这时系统会自动调用该对象的特殊函数--构造函数,来完成清理工作。如:构造函数使用new关键字分配内存,则在对象注销的使用应该使用delete来释放内存,则我们可以在析构函数中调用delete来释放内存。
析构函数:~Time(){} 没返回值 函数名同类名,用~符号,无参 若我们没有定义,则系统会帮我们创建析构函数,不执行任何操作。当我们在构造函数中使用了new来分配内存时,我们应该自己创建一个析构函数。
Time t(12 , 23, 34 ) ; 创建t对象,并对对象的成员赋值。
Time t = Time(12 , 23, 34 ) ; c++标准允许编译器使用两种方式来执行该操作,一种同上面那样,另一种是:调用构造函数创建临时对象,并将该临时对象复制到对象t中,然后丢弃临时对象。
Time t1(12 , 23, 34 ) ; Time t2(12 , 23, 34 ) ; t1 = t2 ;
t1 = t2 ; 默认情况下,同结构体一样,将一个对象赋给同类型的另一个对象时,c++将源对象的每个成员的数据复制到另一个对象对应的数据成员中去,若数据成员存在指针,则可能出现两个对象的指针数据成员指向同一块内存,修改一个对象,则会影响另一个对象,则我们应该重写赋值操作符。
const成员函数:
const T t (12 , 23, 34 ) ; t.show() ; //这行代码不能执行
t.show()不能执行,因为t对象是const常量,show()成员函数不能保证在函数中是否修改了t对象成员数据。要使之能够执行,则应将show()函数定义为const成员函数。在函数声明和定义后面加const关键字,如:
//在Time类中声明
void show() const ;
//在Time.cpp实现
void Time::show() const { //在const成员函数中不能修改成员数据
////
}
const成员函数不能修改成员数据,const对象只能调用const成员函数。非const对象既可以调用const成员函数,也可以调用非const成员函数。同将不需要修改的引用参数或指针参数设置为const一样,我们也应该将不需要修改成员数据的函数设置为const成员函数。
this指针,成员函数中都有个一个this指针,它指向调用该函数的对象本身,我们可以使用它来返回调用对象本身。我们要编写一个比较时间大小的成员函数
//函数声明
const Time & Time::maxTime(const Time& t) const ;
//函数定义
const Time & Time::maxTime(const Time& t) const {
if(this->hour == t.hour ){
if(this->minute == t.minute ) {
if(this->second >= t.second) {
return *this ; //返回当前对象
}else {
return t ;
}
}else if(this->minute > t.minute ){
return *this ;
}else {
return t ;
}
}else if (this->hour > t.hour ){
return *this ;
}else {
return t ;
}
}
在const成员函数中,this的类型是指向const的指针,不能通过this来修改对象的数据成员。
在类中使用常量:
1:我们可能想到使用const定义常量size,如:
class T {
const int size = 30 ;
}
但这样是错误的,因为声明类只是描述类的形式,并没有分配内存空间,不能给数据成员赋值。 但我们可以使用参数序列表在创建对象时赋值:
#include<iostream>
using namespace std ;
class T {
const int size ;
public :
T(int s) : size(s) {} // :size(s) 参数序列表来给size赋值
int main(){
T t(4) ;
return 0 ;
}
在创建对象t时,也会创建const int size成员,并用s赋值, 若不使用参数序列表也会出错。如:T(int s ) { size = s } ; 应该执行到函数内部时,数据size已经定义了,并赋值为默认0,size = s error 因为size 为const 不能修改了。
2:使用static 静态成员:因为静态成员,在对象创建之前就已经存在,是所有对象共享的数据。如:
#include<iostream>
class T {
static const int size ; //也可以在这里赋值的 //static 默认是public
} ;
const int T::size = 30 ; //赋值
int main(){
std::cout << T.size << std::endl ;
}
则size即是静态的,也是个常量。
3:在类中使用枚举:
class T{
enum {size = 12 } ;
double cost[size] ; //size = 12
};
浙公网安备 33010602011771号