1.在c++中,成員變量和成員函數分開存儲
只有非靜態的成員變量才屬於類的變量上,成員變量和成員函數是分開存儲的
- 當定義一個空類,求空類的大小
#include <iostream>
using namespace std;
class Person
{
};
void test1()
{
Person p;
cout << "size of person = " << sizeof(p) << endl;
}
int main()
{
test1();
return 0;
}
原因:c++爲每個空對象都分配一個字節的空間,是爲了區分每個空對象的在內存中的位置;
- 當類中存放多個非靜態成員變量
class Person
{
int a;
int b;
};
返回值:8
原因:每個成員變量佔4個內存空間
- 存放靜態成員變量或者靜態成員函數
返回:1個字節
原因:靜態成員變量或者靜態成員函數,不屬於類的對象上
- 非靜態成員函數
返回:1個字節空間
原因:非靜態成員函數也不屬於類的對象上
2.this指針
c++中的成員變量和成員函數是分開存儲的
每一個非靜態成員函數只會誕生一個函數實例,也就是說多個同類型的對象會共有同一塊代碼
那麼問題在於:這一塊代碼是怎麼區分哪個對象調用的自己
c++中通過this指針解決上述問題,this指針指向被調用的成員函數所屬的對象
(比如對象p1,p2,p3,當調用p1時候,this指針就指向p1)
this指針是隱含每一個非靜態成員函數內的一種指針
this指針不需要定義,直接使用
this指針的用途:
- 當形參與成員變量同名的時候,可以用this指針來區分
- 在類的非靜態成員函數中返回對象本身,可以用return *this
#include <iostream>
using namespace std;
class Person
{
public:
Person(int age)
{
//第一個用法,形參與成員變量同名的時候,可以用this指針來區分
//this指針指向被調用成員函數所屬的對象
this->age = age;
}
//這裏返回的是引用,不會調用拷貝構造函數
Person& personaddage(Person &p)
{
this->age +=p.age;
//this指向p2的指針,而*this指向的就是p2
return *this;
}
int age;
};
void test01()
{
Person p1(16);
cout << "p1的age" << p1.age << endl;
}
void test02()
{
Person p1(10);
Person p2(10);
p2.personaddage(p1).personaddage(p1).personaddage(p1);
}
TIPS:
- 如果返回的是值,那麼就會調用拷貝構造函數,並不是返回本身,而是返回一個副本(p2',p2'')
- 如果返回的是引用,那麼就是返回的本身,並且不會調用拷貝構造函數
3.空指針調用成員函數
#include <iostream>
using namespace std;
class Person
{
public:
Person()
{
cout << "this is class" << endl;
}
void show()
{
//報錯的原因是傳入的指針爲空
//所以爲了保證代碼的健壯性,會加入:
if(this == NULL)
{
return;
}
cout << "name is " << this->age << endl;
}
int age;
};
void test01()
{
Person *p1 = NULL;
}
4.const修飾成員函數
常函數
- 成員函數後加const後我們稱之爲常函數
- 常函數內不可以修改成員屬性
- 成員屬性聲明時加上關鍵字mutable後,在常函數中依然可以修改
常對象
- 聲明對象前加const稱該對象爲常對象
- 常對象只能調用常函數
#include <iostream>
using namespace std;
class Person
{
public:
//this 指針的本質是指針常量,指針的指向是不可以修改的
//如果調用對象p,this指針就不能修改指向
//但是this指針指向的值可以修改
// const person* const this
//在成員函數後面加const修飾的是this指針,讓指針指向的值也不可以修改
void showperson() const
{
this->m_a = 100;
}
int m_a
mutable int m_b; //加上mutable之後,即使在常函數中,也可以修改這個值
};
void test01()
{
Person *p1 = NULL;
const Person p;//常對象中也不可以修改普通的成員對象
//常對象只能調用常函數
//因爲常對象不可以修改屬性,普通函數可以修改屬性,所以常對象不可以調用普通成員函數
}