C++对象模型
成员变量和成员函数分开存储
只有普通成员变量才属于对象,函数和静态成员变量都不属于对象
class Person{
public:
int a;
int b;
char c;
void prt() {
cout << a << endl << b << c;
}
};
class VD{
};
void test() {
Person p;
VD v;
cout << sizeof p << endl; //12,内存对齐,4 + 4 + 4,而函数不占空间
cout << sizeof v << endl; //1
//编译器会为空对象分配一个占位的1字节空间
}
this指针
既然多个对象会共享一个成员函数,即成员函数只在内存中存储一份,那么这个成员函数怎么区分是哪个对象调用的自己呢?
通过this指针
this指针指向被调用的成员函数所属的对象,即谁调用函数,this就指向谁
this指针隐含在每一个非静态成员函数内
- 本质
this指针的本质是指针常量,不可以改变指向
- 其他用途
- 当形参和成员变量重名时,可以用this来区分(和Java一样)
this->age = age;
- 在类的非静态成员函数中返回对象本身时,可使用
return *this;
- 当形参和成员变量重名时,可以用this来区分(和Java一样)
空指针调用成员函数
空指针可以调用成员函数,条件是此函数内没有用到this指针
class Person{
public:
int age;
Person() {
age = 10;
}
void showClassName() {
cout << "Class:Person";
}
void showAge() {
// if (!this) return; //这行代码可以提高程序的健壮性
cout << age; //编译器会改为cout << this->age; 用到了this指针
}
};
void test() {
Person* p = nullptr;
p->showClassName(); //可以运行
p->showAge(); //程序会崩
}
const
修饰成员函数、成员变量
常函数
- 成员函数后加
const
我们称这个函数为常函数 - 常函数内不可以修改成员属性
- 成员属性声明时加关键字
mutable
后,在常函数中可修改
class Person{
public:
int age;
mutable int b; //b可以改
void func() const { //常函数,事实上,const修饰的是this指针
//age = 100; //不可修改,报错
b = 200; //正确
}
};
常对象
- 声明对象前加
const
称该对象为常对象 - 常对象的属性不可修改,除非该属性用
mutable
修饰 - 常对象只能调用常函数,防止通过普通函数间接的修改普通属性
void test() {
const Person p1;
p1.age = 100; //错误
p1.b = 200; //正确
}
友元
在程序里,有些私有属性也想让类外的一些特殊函数或类进行访问,这就需要用到友元的技术
友元的目的就是让一个函数或者类访问另一个类中的私有成员
关键字 friend
三种实现
- 类做友元
class House;
class GoodGay{
public:
GoodGay(); //类外实现
void visit(); //类外实现
House* house; //构造函数内必须初始化此指针
};
class House {
friend class GoodGay; //GoodGay是本类的好朋友,可以访问本类的私有成员bedroom
private:
string bedroom;
public:
string livingRoom;
House(); //类外实现
};
House::House() { //类外实现构造函数
livingRoom = "客厅";
bedroom = "卧室";
}
GoodGay::GoodGay() { //类外实现构造函数
house = new House;
}
void GoodGay::visit() { //类外实现成员函数
cout << "好基友正在访问:" << house->livingRoom << endl;
cout << "好基友正在访问:" << house->bedroom << endl;
}
void test() {
GoodGay goodGay;
goodGay.visit();
}
- 全局函数做友元
class House {
friend void myHouse(); //这个全局函数是本类的好朋友,所以可以访问本类的私有成员
//friend void GoodGay::visit(); //GoodGay类下的visit成员函数是本类的好朋友,成员函数做友元
private:
string bedroom;
public:
string livingRoom;
House() {
livingRoom = "客厅";
bedroom = "卧室";
}
};
void myHouse() {
House house;
cout << "好基友正在访问:" << house.livingRoom << endl;
cout << "好基友正在访问:" << house.bedroom << endl;
}
- 成员函数做友元
见上方