忆江南-春风

象蜗牛一样生活
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

对象和类1(六)

Posted on 2013-10-18 16:30  忆江南-春风  阅读(181)  评论(0编辑  收藏  举报

从今天开始,我们将要接触到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
};