1. 静态成员
在成员变量/函数前加关键字static,称为静态成员(static member)
静态成员分为:
静态成员变量示意:
#include <iostream>
using namespace std;
class person {
public:
static int m_A;
};
int person::m_A = 100;
void test01() {
person p;
cout << p.m_A << endl;
person p2;
p2.m_A = 200;
cout << p.m_A << endl;
}
int main() {
test01();
return 0;
}
运行上面的代码可以发现第二次访问p中的m_A成员时值已经被改为了200(所有对象共享静态成员的数据):
因此,访问静态成员变量有两种方式:
person p;
cout << p.m_A << endl; //通过对象进行访问
cout << person::m_A << endl; //通过类名进行访问
静态成员变量也有访问权限,可以设置private防止类外访问。
静态成员函数示意:
#include <iostream>
using namespace std;
class person {
public:
int m_B;
static int m_A;
static void func() {
m_A = 100; // 静态成员函数可以访问静态成员变量
// m_B = 200; 报错,无法区分是哪个对象的m_B
cout << "static void func 调用" << endl;
}
};
int person::m_A = 0;
//
//void test01() {
// person p;
// cout << p.m_A << endl;
// person p2;
// p2.m_A = 200;
// cout << p.m_A << endl;
//}
void test02() {
person p;
p.func(); //通过对象访问
person::func(); //通过类名访问
}
int main() {
//test01();
test02();
return 0;
}
同样,静态成员函数有通过对象/类名两种访问方法,有访问权限。
静态成员函数可以访问静态成员变量,不可以访问非静态成员变量。
2. C++对象模型和this指针
C++编译器为每个空对象分配一个字节空间(8bit):
非静态成员变量,属于类的对象上,记入类空间,静态成员变量,不属于类对象上,不计入空间。
成员变量和成员函数分开存储,成员函数不属于类对象上。
每一个非静态成员函数只会诞生一份函数实例,多个同类型对象会共用一块代码。
this指针(this pointer)指向被调用的成员函数所属对象——用来区分哪个对象调用自己:
this指针隐含在每个非静态成员函数内,无需定义可直接使用。
#include <iostream>
using namespace std;
class person {
public:
int age;
person(int age) {
this->age = age;
}
person& addage(person &p) {
this->age += p.age; //this解决名称冲突
//this指向p2的指针,*指向p2本体
return *this; //返回对象本身
}
};
void test01() {
person p1(18);
cout << "age = " << p1.age << endl;
person p2(10);
p2.addage(p1).addage(p1).addage(p1); //链式编程思想
cout << "age = " << p2.age << endl;
}
int main() {
test01();
system("pause");
return 0;
}
使用引用方式&返回,不会新建对象,用this进行重复累加p1_age操作:
this指针的本质是指针常量,this指针的指向不可修改(只能修改指向的值)
3.const修饰成员函数
在成员函数后加const修饰的是this指针指向的值,使之不可修改。
常对象不能修改成员属性,但可以修改静态变量的值,加了mutable的值,常对象也能修改。
#include <iostream>
using namespace std;
class person {
public:
static int nation;
};
int person::nation = 0;
void test01() {
const person p;
p.nation = 1;
cout << p.nation << endl;
}
int main() {
test01();
system("pause");
return 0;
}
//输出结果为1
4.友元
友元(friend)的目的是让一个函数/类访问另一个类中的私有(private)成员。
全局函数做友元:
#include <iostream>
#include <string>
using namespace std;
class building {
friend void goodfriend(building* build); // 全局函数做友元
public:
building() {
m_livingroom = "live";
m_bedroom = "bed";
}
public:
string m_livingroom;
private:
string m_bedroom;
};
void goodfriend(building *build) {
cout << "goodfriend visiting:" << build->m_livingroom << endl;
cout << "goodfriend visiting:" << build->m_bedroom << endl;
}
int main() {
building myhome;
goodfriend(&myhome);
system("pause");
return 0;
}
类外的goodfriend函数可以访问类中的private成员m_bedroom。
类作为友元:
#include <iostream>
#include <string>
using namespace std;
class building {
// friend void goodfriend(building* build); 全局函数做友元
friend class goodfriend; //类作为友元
public:
building() {
m_livingroom = "客厅";
m_bedroom = "卧室";
}
string m_livingroom;
private:
string m_bedroom;
};
class goodfriend {
public:
goodfriend();
void visit();
building* build;
};
goodfriend::goodfriend() {
build = new building;
}
void goodfriend::visit() {
cout << "goodfriend visiting:" << build->m_livingroom << endl;
cout << "goodfriend visiting:" << build->m_bedroom << endl;
}
void test01() {
goodfriend g1;
g1.visit();
}
//void goodfriend(building *build) {
// cout << "goodfriend visiting:" << build->m_livingroom << endl;
// cout << "goodfriend visiting:" << build->m_bedroom << endl;
//}
int main() {
//goodfriend(&myhome);
test01();
system("pause");
return 0;
}
成员函数作为友元:
#include <iostream>
#include <string>
using namespace std;
class building;
class goodfriend {
public:
goodfriend();
void visit1();
void visit2();
building* build;
};
class building {
// friend void goodfriend(building* build); 全局函数做友元
// friend class goodfriend; 类作为友元
friend void goodfriend::visit1(); // 成员函数作为友元
public:
building() {
m_livingroom = "客厅";
m_bedroom = "卧室";
}
string m_livingroom;
private:
string m_bedroom;
};
goodfriend::goodfriend() {
build = new building;
}
void goodfriend::visit1() {
cout << "goodfriend visiting:" << build->m_livingroom << endl;
cout << "goodfriend visiting:" << build->m_bedroom << endl;
}
void goodfriend::visit2() {
cout << "goodfriend visiting:" << build->m_livingroom << endl;
// cout << "goodfriend visiting:" << build->m_bedroom << endl;
}
void test01() {
goodfriend g1;
g1.visit1();
g1.visit2();
}
//void goodfriend(building *build) {
// cout << "goodfriend visiting:" << build->m_livingroom << endl;
// cout << "goodfriend visiting:" << build->m_bedroom << endl;
//}
int main() {
//goodfriend(&myhome);
test01();
system("pause");
return 0;
}
注意,goodfriend的定义要放在building前,否则building将无法定义其内部成员函数的友元,又因goodfriend内有创建building类的指针,所以要在其定义前声明building,最后,友元的设定需放在类定义的最开始。