類和對象——四個默認成員函數+運算符重載


1.類和對象的基礎知識,如類的定義,訪問限定符,面向對象封裝性,對象的大小計算等等。

類的定義:類(Class)實際上是某種類型的對象變量和方法的原型.類是從一些具有相同屬性或功能的具體實例中抽象出共有的一些屬性。
類是一個新的數據類型,它和結構體有點相似,是由不同數據類型組成的集合體,但類要比結構體增加了操作數據的行為,這個行為就是函數,還有一個區別就是類內存在類成員訪問的修飾限定符。
·class是定義類結構體的關鍵字,花括號內被稱為類體或類空間
·類名是一個新的數據類型,通過類名可以聲明對象
·類的成員有函數和數據兩種類型
·花括號內是定義和聲明類成員的地方,關鍵字public,private,protected是類成員的訪問限定符
注意:定義類結構體和定義結構體時花括號后要有分號
定義一個簡單的類

class Person //類名
{
public : //訪問限定符
void Display () //成員函數
{
cout<<_name <<"-"<< _sex<<"-" <<_age<< endl;
}
public : //成員變量
char*_name;
char*_ sex;
int _age; // 年齡
};
void Test ()
{
Person p ; //將類先實例化
p._name = "jack";
p._age = 10;
p._sex = "男 ";
p.Display ();
Person* ptr = &p;
ptr->name="peter";
ptr->_age = 18;
ptr->Display ();
}

成員函數的聲明和定義
在類內定義成員函數

class person
{
public:
void Display()
{
cout<<_name<<"-"<<_sex<<"-"<<age<<endl;
}
public:
char*_name;
char*_sex;
int _age;
};

類外定義成員函數

class person
{
public:
void Display()
{}
public:
char*_name;
char*_sex;
int _age;
};
person::void person Display()//類外定義需要加限定域
{
cout<<_name<<"-"<<_sex<<"-"<<age<<endl;
}

關於對象的大小計算,與結構體的內存對齊規則相同
·第一個成員在與結構體變量偏移量為0的地址處。
·其他成員變量要對齊到某個數字(對齊數)的整數倍的地址處。 //對齊數 = 編譯器默認的一個對齊數 與 該成員大小的較小值。
·VS中默認的值為8 gcc中的默認值為4
·結構體總大小為最大對齊數(每個成員變量除了第一個成員都有一個對齊數)的整數倍。
·如果嵌套了結構體的情況,嵌套的結構體對齊到自己的最大對齊數的整數倍處,結構體的整體大小就是所有最大對齊數(含嵌套結構體 的對齊數)的整數倍。
類內部的成員函數不計入對象大小之內,成員函數放在公共代碼區
當成員函數為空時,其大小為1
*

2.四個默認成員函數及運算符重載相關知識

  • 當我們在定義一個類的同時,系統會默認生成默認的六個成員函數,它們分別是構造函數,拷貝構造函數,析構函數,賦值操作符重載,取地址符重載,const修飾的取地址符重載
    (1)構造函數
    成員變量為私有的,要對它們進行初始化,必須用一個公有成員函數來進行。同時這個函數應該有且僅在定義對象時自動執行一次,這時 調用的函數稱為構造函數(constructor) 。
    構造函數是特殊的成員函數,其特征如下:

    ·函數名與類名相同, 無返回值, 對象構造(對象實例化)時系統自動調用對應的構造函數。
    ·構造函數可以重載(一般選擇在類內定義)
    · 如果類定義中沒有給出構造函數,則C++編譯器自動產生一個缺省的構造函數,但只要我們定義了一個構造函數,系統就不會自動 生成缺省的構造函數。
    · 無參的構造函數和全缺省值的構造函數都認為是缺省構造函數,並且缺省的構造函數只能有一個。

class Date
{
public:
Date()//無參構造函數
{}
Data(int year,int month,int day)//帶參構造函數
{
_year=year;
_month=month;
_day=day;
}
Data(int year=2017,int month=03,int day=09)//缺省參數的構造函數
{
_year=year;

_month=month;

_day=day;

}
Data(int year=z017,int month=06))//半缺省參數的構造函數
{
_year=year;


_month=month;


_day=25;


}
private:
int_name;
int_sex;
int _age;
};
void TestDate1()
{
Data d1(); // 調用無參構造函數
Data d2(2017,06,25); // 調用帶參構造函數
Data d1();)//調用缺省參數的構造函數
Data d2(2017,03,09))//調用缺省參數的構造函數
}

(2)拷貝構造函數
創建對象時使用同類對象來進行初始化,這時所用的構造函數稱為拷貝構造函數(Copy Constructor),拷貝構造函數是特殊的構造函數。
特征:
· 拷貝構造函數其實是一個構造函數的重載。
·拷貝構造函數的參數必須使用引用傳參,使用傳值方式會引發無窮遞歸調用。
· 若未顯示定義,系統會默認缺省的拷貝構造函數。缺省的拷貝構造函數會,依次拷貝類成員進行初始化。
下面來實現一個拷貝構造函數

class  Data
{
public:
Data()
{}
Data(const Data &d)//拷貝構造函數
{
_year=d._year;
_month=d._month;
_day=d._day;
}
private:
int _year ;
int _month ;
int _day ;
};

void TestDate1 ()
{
Date d1 ;
// 下面兩種用法都是調用拷貝構造函數,是等價的。
Date d2 (d1); // 調用拷貝構造函數 在這里函數里面存在一個隱含的this指針把d1的值傳給d1,把d2的值傳給this
Date d3 = d1; // 調用拷貝構造函數 在這里函數里面存在一個隱含的this指針把d1的值傳給d1,把d3的值傳給this
}

(3)析構函數
當一個對象的生命周期結束時,C++編譯系統會自動調用一個成員函數,這個特殊的成員函數即析構函數(destructor)
構造函數是特殊的成員函數,其特征如下:
·析構函數在類名加上字符~
·析構函數無參數無返回值
·一個類有且只有一個析構函數。若未顯示定義,系統會自動生成缺省的析構函數。 · 對象生命周期結束時,C++編譯系統系統自動調用析構函數。
·注意析構函數體內並不是刪除對象,而是做一些清理工作

class Date 
{
public :
// 析構函數
~Date()
{}
private :
int _year ;
int _month ;
int _day ;
};


class Array
{
public :
Array (int size)
{
_ptr = (int *)malloc( size*sizeof (int));
}
// 這里的析構函數需要完成清(shi)理(fang)工(kong)作(jian)。
{
if (_ptr )
{
free(_ptr );
_ptr = 0;
}
}
private :
int* _ptr ;
};

運算符的重載
運算符重載特征:
operator+ 合法的運算符 構成函數名(重載<運算符的函數名:operator< ),整個語句沒有返回值類型,類型名就代表返回值類型。
重載運算符以后,不能改變運算符的優先級/結合性/操作數個數。

5個C++不能重載的運算符: .* :: sizeof ?: .
(4)賦值運算符重載
拷貝構造函數是創建的對象,使用一個已有對象來初始化這個准備創建的對象。 賦值運算符的重載是對一個已存在的對象進行拷貝賦值。
運算符實際上是一個函數,運算符的重載即是函數的重載。

Date& operator=(const Date& d)
{
if(this != &d) //=左右兩個對象不為同一個對象再進行賦值操作
{
this->_day = d._day;
this->_month = d._month;
this->_year = d._year;
}
return *this;
}

重載運算符的運算
對於兩個整型變量相加,用戶可以調換兩個加數的位置,但通過重載運算符實現兩個不同類型的對象相加,則不可以。

//前置++
Complex &operator++()
{
_real=real++;
return *this;
}
//后置++
Complex &operator++(int)
{
Complex tmp*this;
real+=1;
return real;
}
//重載賦值運算符
Complex &operator=(int year)
{
_real=real;
}

3.整理隱含的this指針等等,及對運算符重載背后做的事情。

//d1=d2
bool operator==(const date d)
{

return _year==d1.year//_year=>this->_year
&&_month==d1.month
&&_day==d1.day;

}

這里寫圖片描述


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com