1.静态成员函数
静态成员变量:1.所有对象共享一份数据 2.在编译阶段分配内存 3.类内声明,类外初始化
静态成员函数:1.所有对象共享一个函数 3.静态成员函数只能访问静态成员变量
#include<iostream> #include<string> using namespace std; //静态成员函数 class person { public: static void func() //加上static变成静态成员函数 { m_A = 100;//静态成员函数可以访问静态成员变量 //m_B=200;会报错,无法访问 cout << "static void func 的调用" << endl; } static int m_A;//静态成员变量 int m_B;//非静态成员变量 private: static void func2() { cout << "static void func2的调用" << endl; } }; void text1() { //1.通过对象访问 person p; p.func(); //2.通过类名访问 person::func();//不属于某个对象,大家共用,可以直接访问 } int main() { text1(); system("pause"); return 0; }
2.成员变量和成员函数分开存储
在c++中,类内的成员变量和成员函数分开存储,只有非静态成员变量才属于类的对象上
#include<iostream> #include<string> using namespace std; //成员变量和成员函数是分开存储的 class person { }; void text1() { person p; //空对象占用的内存空间为 cout << "sizeof p=" << sizeof(p) << endl; } int main() { text1(); system("pause"); return 0; }
运行结果:
c++会给每个空对象分配一个字节空间,是为了区分空对象占内存的位置,每个空对象也应该有一个独一无二的内存地址,就像我们拿书包或者水杯帮同学占位置
class person { int m_A;//非静态成员变量 };
多了一个非静态成员变量后内存空间为4.
class person { int m_A;//非静态成员变量 static int m_B;//静态成员变量 };
class person { int m_A;//非静态成员变量 static int m_B;//静态成员变量 void func() {}//非静态成员函数 };
class person { int m_A;//非静态成员变量 static int m_B;//静态成员变量 void func() {}//非静态成员函数 static void func2(){}//静态成员函数 };
运行结果都是4.只有非静态成员变量才属于类的对象上
3.this 指针
this指针指向被调用的成员函数所属的对象,不需要定义,可以直接调用
this指针的用途:1.当形参和成员变量同名时,可以用this指针来区分 2.在类的非静态成员函数中返回对象本身,可以用return*this。
#include<iostream> #include<string> using namespace std; class person { public: int age; person(int age) { this->age = age;//不加前面的this->会出错 } void personadd( person& p) { this->age += p.age; } }; //1.解决名称冲突 void text1() { person p1(18); cout << "p1的年龄为:" << p1.age << endl; } //2 返回对象本身用*this void text2() { person p1(10); person p2(10); p2.personadd(p1); cout << "p2的年龄为:" << p2.age << endl; } int main() { text2(); system("pause"); return 0; }
#include<iostream> #include<string> using namespace std; class person { public: int age; person(int age) { this->age = age;//不加前面的this->会出错 } person & personadd( person& p) { this->age += p.age; return *this; } }; //1.解决名称冲突 void text1() { person p1(18); cout << "p1的年龄为:" << p1.age << endl; } //2 返回对象本身用*this void text2() { person p1(10); person p2(10); //链式编程思想 p2.personadd(p1).personadd(p1).personadd(p1).personadd(p1); cout << "p2的年龄为:" << p2.age << endl; } int main() { text2(); system("pause"); return 0; }
注意:引用的话返回值本身,直接返回值的话会拷贝构造出新的,不是原来的值
4.空指针访问成员函数
#include<iostream> #include<string> using namespace std; //空指针调用成员函数 class person { public: void showclassname() { cout << "this is class" << endl; } void showpersonage() { if (this == NULL)//保证代码的健壮性,不会出错 { return; } cout << "age=" << m_age << endl; //相当于cout << "age=" << this->m_age << endl; //但此时this指向空指针 } int m_age; }; void text1() { person* p=NULL; p->showclassname();//正常 p->showpersonage();//报错 } int main() { text1(); system("pause"); return 0; }
5.const修饰成员函数
常函数:
1.成员函数后面加const后我们称这个函数为常函数
2.常函数内不可修改成员属性
3.成员属性声明时加mutable后,在常函数中依然可以修改
常对象:
1.声明对象前加const称该对象为常对象
2.常对象只能调用常函数
#include<iostream> #include<string> using namespace std; //常函数 class person { public: //this指针的本质 是指针常量 指针的指向是不能修改的 //相当于person*const this; //在成员函数后面加上const,修饰的是this指针,让指针指向的值也不能修改 void showperson() const //相当于const person*const this { //m_A=100;会报错,相当于this->m_A=100; this->m_B = 100; } int m_A; mutable int m_B;//加上关键字mutable,在常函数中也可以修改 void func() { } }; void text1() { person p; p.showperson(); } //常对象 void text2() { const person p;//常对象,不能修改 p.m_B = 100;//常对象也可以修改 //常对象只能调用常函数 p.showperson(); //p.func();不能调用普通成员函数,因为普通成员函数可以修改对象 } int main() { text1(); system("pause"); return 0; }
6.友元
生活中,你的客厅public可以给所有客人访问,而你的卧室private只能你自己访问,除此之外,你的好朋友也可以访问,友元的目的就是让一个函数或者类,访问另一个类中私有成员
友元的三种实现:1.全局函数做友元 2.类做友元 3.成员函数做友元
#include<iostream> #include<string> using namespace std; class building { friend void goodGay(building& building);//goodGay是building的好朋友,友元 public: string m_sttingroom;//客厅 building() { m_sttingroom = "客厅"; m_bedroom = "卧室"; } private: string m_bedroom;//卧室 }; //全局函数 void goodGay(building &building) { cout << "好基友的全局函数正在访问:" << building.m_sttingroom << endl; cout << "好基友的全局函数正在访问:" << building.m_bedroom << endl; } void text1() { building b; goodGay(b); } int main() { text1(); system("pause"); return 0; }
#include<iostream> #include<string> using namespace std; class Building; class GoodGay { public: Building* building; GoodGay(); void visit(); //参观函数,访问building中的属性 }; class Building { friend class GoodGay; public: string m_Sittingroom;//客厅 Building(); private: string m_BedRoom;//卧室 }; //类外写成员函数 Building::Building() { m_Sittingroom = "客厅"; m_BedRoom = "卧室"; } GoodGay::GoodGay() { //创建建筑物对象 building = new Building; } void GoodGay::visit() { cout << "好基友正在访问:" << building->m_Sittingroom << endl; cout << "好基友正在访问:" << building->m_BedRoom << endl; } void text1() { GoodGay gg; gg.visit(); } int main() { text1(); system("pause"); return 0; }
#include<iostream> #include<string> using namespace std; class Building; class Goodgay { public: Goodgay(); void visit1();//让他可以访问building中私有成员 void visit2();//让他不能访问 Building * building;//不用指针会报错 }; class Building { friend void Goodgay::visit1(); public: Building(); string m_sitting; private: string m_bed; }; Building::Building() { m_bed = "卧室"; m_sitting = "客厅"; } Goodgay::Goodgay() { building = new Building; } void Goodgay::visit1() { cout << "visit1函数正在访问:" << building->m_sitting << endl; cout << "visit1函数正在访问:" << building->m_bed << endl; } void Goodgay::visit2() { cout << "visit2函数正在访问:" << building->m_sitting << endl; } void text1() { Goodgay gg; gg.visit1(); gg.visit2(); } int main() { text1(); system("pause"); return 0; }