【学习笔记】C++ 对象模型和this指针

目录

1.成员与对象的储存关系

2.this指针

3.空指针调用成员函数

4.const修饰成员函数

5.友元函数


1.成员与对象的储存关系

在C++中,类内的成员变量和成员函数分开存储

只有非静态成员变量才属于类的对象上

#include <iostream>
#include <string>

using namespace std;

class Student
{
};
class Phone
{
public:
    int a;//非静态成员变量属于类的对象上

    static int b;//静态成员变量不属于类的变量上

    static void func(){};
};

int Phone::b=10;

int main()
{
    Student s1;

    cout << sizeof(s1) << endl;//空对象占用内存为1;编译器会给每个空对象分配一个独一无二的内存地址

    Phone p1;

    cout << sizeof(p1) << endl;

    system("pause");

    return 0;
}

2.this指针

每一个非静态成员函数只会诞生一份函数实例,也就是说多个同类型的对象会共用一块代码

那么问题是:这一块代码是如何区分那个对象调用自己的呢

c++通过提供特殊的对象指针,this指针,解决上述问题。this指针指向被调用的成员函数所属的对象

this指针是隐含每一个非静态成员函数内的一种指针

this指针不需要定义,直接使用即可,this指针本身其实是一个指针常量

this指针的用途:

  • 当形参和成员变量同名时,可用this指针来区分
  • 在类的非静态成员函数中返回对象本身,可使用return *this
#include <iostream>
#include <string>

using namespace std;

class Student
{
public:

    Student(int age)
    {

        this->age =age;//等价于Student::age = age;
        
        //this指针指向被调用的成员函数所属的对象

    };

    int age;

Student *StudentAddage01(Student &s)
{

this->age+=s.age;

return this;

};

Student &StudentAddage02(Student &s)
{

this->age+=s.age;

return *this;

};

};

void test01()
{
    Student s1(18);

    cout << "年龄为=" << s1.age << endl;
}

void test02()
{
Student s1(10);

Student s2(19);

cout << "使用this返回的s1年龄为=" << s1.StudentAddage01(s2)->StudentAddage01(s2)->StudentAddage01(s2)->age<< endl;

s1.age=10;

cout << "使用*this返回的s1年龄为=" << s1.StudentAddage02(s2).StudentAddage02(s2).StudentAddage02(s2).age<< endl;

}


int main()
{
    test02();

    system("pause");

    return 0;
}

3.空指针调用成员函数

空指针可以直接访问成员函数的,但是若成员函数使用了this指针则会因为提升指针为空而导致崩溃。

//空指针访问成员函数
class Person {
public:

	void ShowClassName() {
		cout << "我是Person类!" << endl;
	}

	void ShowPerson() {
		if (this == NULL) {
			return;
		}
		cout << mAge << endl;
	}

public:
	int mAge;
};

void test01()
{
	Person * p = NULL;
	p->ShowClassName(); //空指针,可以调用成员函数
	p->ShowPerson();  //但是如果成员函数中用到了this指针,就不可以了
}

int main() {

	test01();

	system("pause");

	return 0;
}

4.const修饰成员函数

常函数:

  • 成员函数后加const后我们称为这个函数为常函数
  • 常函数内不可以修改成员属性
  • 成员属性声明时加关键字mutable后,在常函数中依然可以修改

常对象://不允许修改属性(mutable变量除外

  • 声明对象前加const称该对象为常对象
  • 常对象只能调用常函数

class Person {
public:
	Person() {
		m_A = 0;
		m_B = 0;
	}

	//this指针的本质是一个指针常量,指针的指向不可修改
	//如果想让指针指向的值也不可以修改,需要声明常函数
	void ShowPerson() const {
		//const Type* const pointer;
		//this = NULL; //不能修改指针的指向 Person* const this;
		//this->m_A = 100; //m_A不可更改

		//const修饰成员函数,表示指针指向的内存空间的数据不能修改,除了mutable修饰的变量
		this->m_B = 100;
	}

	void MyFunc() const {
		//mA = 10000;
	}

public:
	int m_A;
	mutable int m_B; //可修改 可变的
};


//const修饰对象  常对象
void test01() {

	const Person person; //常量对象  
	cout << person.m_A << endl;
	//person.mA = 100; //常对象不能修改成员变量的值,但是可以访问
	person.m_B = 100; //但是常对象可以修改mutable修饰成员变量

	//常对象访问成员函数
	person.MyFunc(); //常对象不能调用非const的函数

}

int main() {

	test01();

	system("pause");

	return 0;
}

mutable int m_B; //特殊变量,即使在常函数中也可修改值

5.友元函数

友元函数是为了让外部函数可以访问对象的私有成员,需要在类内加

语法:friend 函数声明;

友元实现

1.全局函数做友元

#include <iostream>
#include <string>

using namespace std;

class Student
{

    friend void test03(Student *s);

public:
    Student(int age)
    {

        this->age = age; //等价于Student::age = age;

        //this指针指向被调用的成员函数所属的对象
    };

    int age;

    Student *StudentAddage01(Student &s)
    {

        this->age += s.age;

        return this;
    };

    Student &StudentAddage02(Student &s)
    {

        this->age += s.age;

        return *this;
    };

private:
    string arr = "你是大傻逼";
};

void test01()
{
    Student s1(18);

    cout << "年龄为=" << s1.age << endl;
}

void test02()
{
    Student s1(10);

    Student s2(19);

    cout << "使用this返回的s1年龄为=" << s1.StudentAddage01(s2)->StudentAddage01(s2)->StudentAddage01(s2)->age << endl;

    s1.age = 10;

    cout << "使用*this返回的s1年龄为=" << s1.StudentAddage02(s2).StudentAddage02(s2).StudentAddage02(s2).age << endl;
}

void test03(Student *s)
{

    cout << s->arr << endl;
}

int main()
{
    Student s1(10);

    test03(&s1);

    system("pause");

    return 0;
}

2.类做友元&成员函数做友元

#include <iostream>
#include <string>

using namespace std;


class Student;
class teacher
{

public:

    void func();
    
};

class Student
{

    friend void test03(Student *s);
    friend void teacher::func();

public:
    Student(int age)
    {

        this->age = age; //等价于Student::age = age;

        //this指针指向被调用的成员函数所属的对象
    };

    int age;

    Student *StudentAddage01(Student &s)
    {

        this->age += s.age;

        return this;
    };

    Student &StudentAddage02(Student &s)
    {

        this->age += s.age;

        return *this;
    };

private:
    string arr = "你是大傻逼";
};


 void teacher::func()
    {
        Student s1(10);

        cout<<s1.arr<<endl;
       
    }

void test01()
{
    Student s1(18);

    cout << "年龄为=" << s1.age << endl;
}

void test02()
{
    Student s1(10);

    Student s2(19);

    cout << "使用this返回的s1年龄为=" << s1.StudentAddage01(s2)->StudentAddage01(s2)->StudentAddage01(s2)->age << endl;

    s1.age = 10;

    cout << "使用*this返回的s1年龄为=" << s1.StudentAddage02(s2).StudentAddage02(s2).StudentAddage02(s2).age << endl;
}

void test03(Student *s)
{

    cout << s->arr << endl;
}

void test04()
{

    teacher t1;

    t1.func();
}

int main()
{
    Student s1(10);

    test03(&s1);

    test04();

    system("pause");

    return 0;
}

在定义friend时注意要先声明再进行定义,否则会出现未定义等类似报错。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值