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;

}

 

posted @ 2022-06-24 17:42  小小是  阅读(71)  评论(0)    收藏  举报