2017年計(jì)算機(jī)等級(jí)考試二級(jí)C++輔導(dǎo):類的其他幾點(diǎn)問題

字號(hào):


    一、拷貝構(gòu)造函數(shù)
    拷貝構(gòu)造函數(shù)在下列情況下被調(diào)用:用已經(jīng)存在的對(duì)象去初始化同一個(gè)類的另一個(gè)對(duì)象;在函數(shù)的參數(shù)中,以傳值方式傳遞類對(duì)象的拷貝;類對(duì)象的值被用做函數(shù)的返回值??截悩?gòu)造函數(shù)和前面說到的轉(zhuǎn)換構(gòu)造函數(shù)有些相似。轉(zhuǎn)換構(gòu)造函數(shù)是把一個(gè)類的對(duì)象轉(zhuǎn)化為另一個(gè)類的對(duì)象;拷貝構(gòu)造函數(shù)是用一個(gè)已經(jīng)存在的對(duì)象的值實(shí)例化該類的一個(gè)新對(duì)象。
    不同對(duì)象間的初始化和賦值的區(qū)別:賦值操作是在兩個(gè)已經(jīng)存在的對(duì)象間進(jìn)行的;而初始化是要?jiǎng)?chuàng)建一個(gè)新的對(duì)象,并且其初值來源于另一個(gè)已存在的對(duì)象。編譯器會(huì)區(qū)別這兩種情況,賦值的時(shí)候調(diào)用重載的賦值運(yùn)算符,初始化的時(shí)候調(diào)用拷貝構(gòu)造函數(shù)。
    如果類中沒有拷貝構(gòu)造函數(shù),則編譯器會(huì)提供一個(gè)默認(rèn)的。這個(gè)默認(rèn)的拷貝構(gòu)造函數(shù)只是簡單地復(fù)制類中的每個(gè)成員。
    #include iostream.h
    #include string.h
    class Date
    {
    int mo, da, yr;
    char* month;
    public:
    Date(int m = 0, int d = 0, int y = 0);
    Date(const Date&);
    ~Date();
    void display() const;
    };
    Date::Date(int m, int d, int y)
    {
    static char* mos[] =
    {
    January, February, March, April, May, June,
    July, August, September, October, November, December
    };
    mo = m; da = d; yr = y;
    if (m != 0)
    {
    month = new char[strlen(mos[m-1])+1];
    strcpy(month, mos[m-1]);
    }
    else
    month = 0;
    }
    Date::Date(const Date& dt)
    {
    mo = dt.mo;
    da = dt.da;
    yr = dt.yr;
    if (dt.month != 0)
    {
    month = new char [strlen(dt.month)+1];
    strcpy(month, dt.month);
    }
    else
    month = 0;
    }
    Date::~Date()
    {
    delete [] month;
    }
    void Date::display() const
    {
    if (month != 0)
    cout << month <<' '<< da << , << yr << std::endl;
    }
    int main()
    {
    Date birthday(6,24,1940);
    birthday.display();
    Date newday = birthday;
    newday.display();
    Date lastday(birthday);
    lastday.display();
    return 0;
    }
    本例中,用到了兩次拷貝構(gòu)造函數(shù)。一個(gè)是使用普通的C++初始化變量的語句:
    Date newday = birthday;
    另一個(gè)是使用構(gòu)造函數(shù)的調(diào)用約定,即把初始化值作為函數(shù)的參數(shù):
    Date lastday(birthday);
    二、類的引用
    在函數(shù)參數(shù)和返回值中,如果一定要使用傳值方式,那么使用類對(duì)象的引用,是一個(gè)提高效率的方法。
    類的數(shù)據(jù)成員也可以是一個(gè)引用,但必須注意:第一,一個(gè)引用必須初始化。通常一個(gè)類對(duì)象并不會(huì)像結(jié)構(gòu)那樣用大括號(hào)來初始化,而是調(diào)用構(gòu)造函數(shù)。因此在構(gòu)造函數(shù)里必須初始化類當(dāng)中的引用成員。第二,引用是一個(gè)別名。盡管類里面的引用在使用方式上看起來和類的一般數(shù)據(jù)成員沒有什么區(qū)別,但是作用在其上的操作,實(shí)際上是對(duì)用來初始化它的那么對(duì)象進(jìn)行的。
    #include iostream.h
    class Date
    {
    int da, mo, yr;
    public:
    Date(int d,int m,int y)
    { da = d; mo = m; yr = y; }
    void Display() const
    { cout << da << '/' << mo << '/' << yr; }
    };
    class Time
    {
    int hr, min, sec;
    public:
    Time(int h, int m, int s)
    { hr = h; min = m; sec = s; }
    void Display() const
    { cout << hr << ':' << min << ':' << sec; }
    };
    class DateTime
    {
    const Date& dt;
    const Time& tm;
    public:
    DateTime(const Date& d, const Time& t) : dt(d), tm(t)
    {
    //empty
    }
    void Display() const
    {
    dt.Display();
    cout << ' ';
    tm.Display();
    }
    };
    int main()
    {
    Date today(7,4,2004);
    Time now(15,20,0);
    DateTime dtm(today, now);
    dtm.Display();
    return 0;
    }
    我們來看看這個(gè)程序中DateTime的構(gòu)造函數(shù)的格式:冒號(hào)操作符引出了一個(gè)參數(shù)初始化表。必須使用這種格式來初始化引用數(shù)據(jù)成員,而不可以在函數(shù)體內(nèi)來進(jìn)行初始化工作。如果構(gòu)造函數(shù)像上例一樣不是內(nèi)聯(lián)的,那么不要在類聲明中構(gòu)造函數(shù)的原型上使用冒號(hào)和初始化值表,而是像下面這樣,把參數(shù)初始化表放在定義構(gòu)造函數(shù)的地方:
    Class DateTime
    {
    const Date& dt;
    const Time& tm;
    public:
    DateTime(const Date& d,const Time& t);
    }
    DateTime::DateTime(const Date& d,const Time& t):dt(d),tm(t)
    {
    //empty
    }
    可以使用構(gòu)造函數(shù)的參數(shù)初始化表來初始化任何數(shù)據(jù)成員。特別是常量數(shù)據(jù)成員,和引用一樣,只能在參數(shù)初始化表里進(jìn)行初始化,這是因?yàn)椴豢梢栽跇?gòu)造函數(shù)內(nèi)部為常量數(shù)據(jù)成員賦值。
    當(dāng)一個(gè)類含有引用數(shù)據(jù)成員時(shí),一旦引用被實(shí)例化和初始化以后,就無法修改它的值,所以該類不可能徹底地重載賦值運(yùn)算符函數(shù)。