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

字號:


    一、拷貝構(gòu)造函數(shù)
    拷貝構(gòu)造函數(shù)在下列情況下被調(diào)用:用已經(jīng)存在的對象去初始化同一個類的另一個對象;在函數(shù)的參數(shù)中,以傳值方式傳遞類對象的拷貝;類對象的值被用做函數(shù)的返回值??截悩?gòu)造函數(shù)和前面說到的轉(zhuǎn)換構(gòu)造函數(shù)有些相似。轉(zhuǎn)換構(gòu)造函數(shù)是把一個類的對象轉(zhuǎn)化為另一個類的對象;拷貝構(gòu)造函數(shù)是用一個已經(jīng)存在的對象的值實例化該類的一個新對象。
    不同對象間的初始化和賦值的區(qū)別:賦值操作是在兩個已經(jīng)存在的對象間進行的;而初始化是要創(chuàng)建一個新的對象,并且其初值來源于另一個已存在的對象。編譯器會區(qū)別這兩種情況,賦值的時候調(diào)用重載的賦值運算符,初始化的時候調(diào)用拷貝構(gòu)造函數(shù)。
    如果類中沒有拷貝構(gòu)造函數(shù),則編譯器會提供一個默認的。這個默認的拷貝構(gòu)造函數(shù)只是簡單地復(fù)制類中的每個成員。
    #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ù)。一個是使用普通的C++初始化變量的語句:
    Date newday = birthday;
    另一個是使用構(gòu)造函數(shù)的調(diào)用約定,即把初始化值作為函數(shù)的參數(shù):
    Date lastday(birthday);
    二、類的引用
    在函數(shù)參數(shù)和返回值中,如果一定要使用傳值方式,那么使用類對象的引用,是一個提高效率的方法。
    類的數(shù)據(jù)成員也可以是一個引用,但必須注意:第一,一個引用必須初始化。通常一個類對象并不會像結(jié)構(gòu)那樣用大括號來初始化,而是調(diào)用構(gòu)造函數(shù)。因此在構(gòu)造函數(shù)里必須初始化類當(dāng)中的引用成員。第二,引用是一個別名。盡管類里面的引用在使用方式上看起來和類的一般數(shù)據(jù)成員沒有什么區(qū)別,但是作用在其上的操作,實際上是對用來初始化它的那么對象進行的。
    #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;
    }
    我們來看看這個程序中DateTime的構(gòu)造函數(shù)的格式:冒號操作符引出了一個參數(shù)初始化表。必須使用這種格式來初始化引用數(shù)據(jù)成員,而不可以在函數(shù)體內(nèi)來進行初始化工作。如果構(gòu)造函數(shù)像上例一樣不是內(nèi)聯(lián)的,那么不要在類聲明中構(gòu)造函數(shù)的原型上使用冒號和初始化值表,而是像下面這樣,把參數(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ù)初始化表里進行初始化,這是因為不可以在構(gòu)造函數(shù)內(nèi)部為常量數(shù)據(jù)成員賦值。
    當(dāng)一個類含有引用數(shù)據(jù)成員時,一旦引用被實例化和初始化以后,就無法修改它的值,所以該類不可能徹底地重載賦值運算符函數(shù)。