c++(八)
静态成员
在成员变量和成员函数前加上关键字static,称为静态成员
静态成员分为静态成员变量和静态成员函数
静态成员函数
所有对象共享同一个函数
静态成员函数只能访问静态成员变量
静态成员变量的访问方式:
1.通过对象进行访问Person p;p.func();
2. 通过类名进行访问Person::func();
静态成员变量
所有对象共享同一份数据(有对象改过数据值之后,再度访问是修改过后的值)
在编译阶段分配内存(在全局区)
类内声明,类外初始化
class Person {
Public:
static int m_A;
};
int Person::m_A=100; //类外初始化
静态成员变量的访问方式:
1.通过对象进行访问Person p;p.m_A
2. 通过类名进行访问Person::m_A
静态成员变量也有访问权限
c++对象模型和this指针
成员变量和成员函数分开存储
在c++中,类中的成员变量和成员函数分开存储
只有非静态成员变量才属于类的对象上,占用对象空间
静态成员变量和函数不占用对象空间
每一个非静态成员函数只会诞生一份函数实例,多个同类型的对象会共用一块代码
c++通过提供特殊的对象指针this指针,解决问题,this指针指向被调用的成员函数所属的对象
this指针是隐含在每一个非静态成员函数内的一种指针,不需要定义,直接使用就可以了
当形参和成员变量同名时,可以使用this指针来区分
在类的非静态成员函数中返回对象本身,可以使用return *this
class Person
{
public:
Person(int age)
{
age=age;
}
int age;
}
void test01()
{
Person p1(18);
cout<<p1.age<<endl;//输出的是一个随机数,因为在class Person中成员函数中形参和成员变量的名字一样
//如果想要改正,有两个方法,第一种是命名规范,可以将成员变量命名为m_age;第二种是使用this指针thsi->age=age;this指向p1的指针,*this指向的是p1这个对象本体
}
Person& PersonAddAge(Person &p)//这里如果返回的时Person的话,相当于每次都会拷贝一个新的出来,最后的结果是20,因为每次都是复制的对象调用的;所以要加上引用才可以
{
this->age += p.age;
//this指向p2的指针,而*this指向的就是p2这个对象的本体
return *this
}
返回对象本身用*this
void test01()
{
Person p1(10);
Person p2(10);
p2.PersonAddAge(p1).PersonAddAge(p1).PersonAddAge(p1);//因为想接着调用PersonAddAge所以需要有对象才可以接着调用PersonAddAge,要返回一个对象才可以
}
c++空指针也是可以调用成员函数的,但是也要注意有没有用到this指针
如果用到this指针,需要加以判断保证代码的健壮性,空指针的话无法访问里面的属性
常函数
成员函数后加const后我们称这个函数为常函数void showPerson()const { cout《《endl }
常函数内不可以修改成员属性
成员属性声明时加关键字mutable后,在常函数中仍然可以修改,这是一个特殊声明
this指针的本质是 指针常量,指针的指向是不可以修改的 实际上是Person
8const this; 指针的指向是不可以修改的,但是指针指向的值是可以修改的,但是如果我们在函数的后面加上const相当于const Person* const this 指针的指向和指针指向的值都不可以进行修改了
常对象
声明对象前加const称该对象为常对象 const Person p;如果成员变量前没有加mutable,使用p.m_A=100;是会进行报错的,因为无法进行修改,但是如果变量前加上之后,是可以
进行修改的
常对象只能调用常函数
友元
友元的目的就是让一个函数或者类 访问另一个类中私有成员
友元的关键字就是friend
友元的三种实现
全局函数做友元
类做友元
成员函数做友元
点运算符(.)用于结构体/类变量 或者对象 访问成员。A.B则A为对象或者结构体;
class Building
{
//gooGay全局函数是building的好朋友,可以访问Building的私有成员
friend void goodGay(Building *building);
public:
Building()
{
this->m_SittingRoom = "客厅";
this->m_BedRoom = "卧室";
}
public:
string m_SittingRoom;//客厅
private:
string m_BedRoom;//卧室
};
//全局函数
void goodGay(Building *building)
{
cout << "全局函数访问" << building->m_SittingRoom << endl;
cout << "全局函数访问" << building->m_BedRoom << endl;
}
void test01()
{
Building b;
goodGay(&b);//因为全局函数中是指针所以这里把地址传过去
}
//类做友元
//类做友元
class Building
{
//GoodGay类是本来的好朋友,可以访问本类中私有成员
friend class GoodGay;
public:
Building();//类内定义,在类外进行实现
public:
string m_Sittingroom;//客厅
private:
string m_Bedroom;//卧室
};
Building::Building()//Building::相当于写一个Building()构造函数的作用域
{
m_Sittingroom = "客厅";
m_Bedroom = "卧室";
}
class GoodGay
{
public:
GoodGay();
public:
void visit();//参观函数 访问Building中的属性
Building * building;
};
GoodGay::GoodGay()
{
//有Building指针,可以进行创建建筑物的对象,使用building指针指向新new出的对象
building = new Building;
}
//也可以不进行类外定义,但是要把Building类写在GoodGay前面,否则会报错
void GoodGay::visit()
{
cout << "好基友类正在访问: " << building->m_Sittingroom << endl;
cout << "好基友类正在访问: " << building->m_Bedroom << endl;
}
void test01()
{
GoodGay gg;//创建goodgay对象调用构造函数建立building对象,building
//构造函数给属性赋初值
gg.visit();//调用visit()函数访问building属性
}
int main()
{
test01();
system("pause");
return 0;
}
//成员函数做友元
class Building;
class GoodGay
{
public:
GoodGay();
public:
void visit();//参观函数 让其可以访问Building中的私有属性
void visit2();//参观函数2 让其不可以访问Building中的私有属性
Building * building;
};
class Building
{
//告诉编译器 GoodGay类下的visit成员函数作为本类的好朋友,可以访问私有成员
friend void GoodGay::visit();
public:
Building();//类内定义,在类外进行实现
public:
string m_Sittingroom;//客厅
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 GoodGay::visit2()
{
cout << "好基友类正在访问: " << building->m_Sittingroom << endl;
//cout << "好基友类正在访问: " << building->m_Bedroom << endl;
}
//如果building的class类在前,goodgay的class类在后,会因为顺序放错了有问题的,必须要building在后面,原因很简单
//程序是一行行的执行的,走到building时遇见了friend void goodgay::visit();
//而这个时候goodgay类还未创建,就没有其中的visit成员函数,所以会报错
//这样的话在visit访问私有成员时仍然会报错
//而且在防止构造函数的时候也要确保其在visit这样的成员函数之前
void test01()
{
GoodGay gg;
gg.visit();
}
int main()
{
test01();
system("pause");
return 0;
}
浙公网安备 33010602011771号