C++类和对象之对象模型和this指针

文章目录

  • [4 类和对象](#4 类和对象)
    • [4.3 C++对象模型和this指针](#4.3 C++对象模型和this指针)
      • [4.3.1 成员变量和成员函数分开存储](#4.3.1 成员变量和成员函数分开存储)
      • [4.3.2 this指针概念](#4.3.2 this指针概念)
      • [4.3.3 空指针访问成员函数](#4.3.3 空指针访问成员函数)
      • [4.3.4 const修饰成员函数](#4.3.4 const修饰成员函数)
      • [4.3.5 GradeBook类](#4.3.5 GradeBook类)

4 类和对象


4.3 C++对象模型和this指针


4.3.1 成员变量和成员函数分开存储


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

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

例4.3.1

c 复制代码
#include <iostream>

using namespace std;

class Person
{
public:
	Person()
	{
		mA = 0;
	}
	//非静态成员变量占对象空间
	int mA;
	//静态成员变量不占对象空间
	static int mB;
	//函数也不占对象空间,所有函数共享一个函数实例
	void func()
	{
		cout << "mA:" << this->mA << endl;
	}
	//静态成员函数也不占对象空间
	static void sfunc()
	{

	}
};

int main()
{

	cout << sizeof(Person) << endl;

	return 0;
}

​ 结果如下:

c 复制代码
4

Process returned 0 (0x0)   execution time : 0.013 s
Press any key to continue.

4.3.2 this指针概念


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

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

​ this指针不需要定义,直接使用即可。

​ this指针的用途:

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

例4.3.2

c 复制代码
#include <iostream>

using namespace std;

class Person
{
public:

	Person(int age)
	{
		//1、当形参和成员变量同名时,可用this指针来区分
		this->age = age;
	}

	Person& PersonAddPerson(Person p)
	{
		this->age += p.age;
		//返回对象本身
		return *this;
	}

	int age;
};

void test01()
{
	Person p1(10);
	cout << "p1.age = " << p1.age << endl;

	Person p2(10);
	p2.PersonAddPerson(p1).PersonAddPerson(p1).PersonAddPerson(p1);
	cout << "p2.age = " << p2.age << endl;
}

int main()
{
	test01();

	return 0;
}

​ 结果如下:

c 复制代码
p1.age = 10
p2.age = 40

Process returned 0 (0x0)   execution time : 0.026 s
Press any key to continue.

4.3.3 空指针访问成员函数


  • C++中空指针也是可以调用成员函数的,但是也要注意有没有用到this指针。

  • 如果用到this指针,需要加以判断保证代码的健壮性。

例4.3.3

c 复制代码
#include <iostream>

using namespace std;

//空指针访问成员函数
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();

	return 0;
}

​ 结果如下:

c 复制代码
我是Person类!

Process returned 0 (0x0)   execution time : 0.003 s
Press any key to continue.

4.3.4 const修饰成员函数


常函数:

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

常对象:

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

例4.3.4

c 复制代码
#include <iostream>

using namespace std;

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

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

		//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();

	return 0;
}

​ 结果如下:

c 复制代码
0

Process returned 0 (0x0)   execution time : 0.008 s
Press any key to continue.

4.3.5 GradeBook类


​ 题目如下:

​ 上机实验一,参考上课范例,完成 GradeBook 类(class)设计。

​ 将类定义(class definition)写在 GradeBook.h 中。 将成员函数(member function)写在 GradeBook.cpp 中。编程一个主程序(main)创建两个 GradeBook 对象,测试类的所有成员函数。

GradeBook

c 复制代码
-courseName: string //at most 25 characters
-studentCount : int //number of student
-grade: double[] //double array to hold student grades
+setCourseName(name:string)
+setStudentCount(id : int)
+getCourseName():string
+getStudentCount():int
+print() //to display information of GradeBook object

​ 程序接口示范

​ 编程设计者 王小明 221040700101

​ 请输入课程名称:Object Oriented Programming

​ 请输入学生人数: 120

​ 利用 getCourseName 以及 getStudentCount 显示第一个对象的信息:

​ 课程名称:Object Oriented Programming

​ 学生人数: 120

​ 请输入课程名称:Linear Algebra

​ 请输入学生人数: 125

​ 利用 print 显示第二个对象的信息:

​ 课程名称:Linear Algebra

​ 学生人数: 125

​ 解答如下:

​ main.cpp

c 复制代码
#include <iostream>
#include "Person.h"
using namespace std;

int main()
{
    Person myPerson;
    // Person myPerson("S.M.Wang", 070145, "莲花路200号");

    cout << "请输入姓名:" ;
    string name;
    cin >> name;

    cout << "请输入ID:" ;
    int id;
    cin >> id;

    cout << "请输入住址:" ;
    string address;
    cin >> address;

    myPerson.setName(name);
    myPerson.setID(id);
    myPerson.setAddress(address);

    myPerson.print();
    return 0;
}

Person.h

c 复制代码
#include <iostream>
 
using namespace std;
 
class Person
{
public:
    Person();
    Person(string name, int id, string address);
    ~Person();
 
    void setPerson(string name, int id, string address);
    void setName(string name);
    void setID(int id);
    void setAddress(string address);
 
    string getName();
    int getID();
    string getAddress();
 
    void print(); // outPutResult
private:
    string Name;
    int ID;
    string Address;
};

Person.cpp

c 复制代码
#include "Person.h"
 
using namespace std;
 
Person::Person()
{
    Name = "S.M.Wang";
    ID = 070145;
    Address = "莲花路200号";
}
 
Person::Person(string name, int id, string address)
{
    setPerson(name, id, address);
}
 
Person::~Person()
{
    cout << "object Destructor is called" << endl;
}
 
 
void Person::setPerson(string name, int id, string address)
{
    Name = name;
    ID = id;
    Address = address;
}
 
 
void Person::setName(string name)
{
    Name = name;
}
 
void Person::setID(int id)
{
    ID = id;
}
 
void Person::setAddress(string address)
{
    Address = address;
}
 
string Person::getName()
{
    return Name;
}
 
int Person::getID()
{
    return ID;
}
 
string Person::getAddress()
{
    return Address;
}
 
void Person::print()
{
    cout << "姓名:" << getName() << endl;
    cout << "ID:" << getID() << endl;
    cout << "住址:" << getAddress() << endl;
}

结果如下:

c 复制代码
请输入姓名:S.M.Wang
请输入ID:070145
请输入住址:莲花路200号
姓名:S.M.Wang
ID:70145
住址:莲花路200号
object Destructor is called

Process returned 0 (0x0)   execution time : 27.263 s
Press any key to continue.
相关推荐
敲上瘾1 分钟前
操作系统的理解
linux·运维·服务器·c++·大模型·操作系统·aigc
不会写代码的ys7 分钟前
【类与对象】--对象之舞,类之华章,共绘C++之美
c++
兵哥工控10 分钟前
MFC工控项目实例三十二模拟量校正值添加修改删除
c++·mfc
长弓聊编程20 分钟前
Linux系统使用valgrind分析C++程序内存资源使用情况
linux·c++
cherub.27 分钟前
深入解析信号量:定义与环形队列生产消费模型剖析
linux·c++
暮色_年华41 分钟前
Modern Effective C++item 9:优先考虑别名声明而非typedef
c++
重生之我是数学王子1 小时前
QT基础 编码问题 定时器 事件 绘图事件 keyPressEvent QT5.12.3环境 C++实现
开发语言·c++·qt
我们的五年1 小时前
【Linux课程学习】:进程程序替换,execl,execv,execlp,execvp,execve,execle,execvpe函数
linux·c++·学习
做人不要太理性2 小时前
【C++】深入哈希表核心:从改造到封装,解锁 unordered_set 与 unordered_map 的终极奥义!
c++·哈希算法·散列表·unordered_map·unordered_set
程序员-King.2 小时前
2、桥接模式
c++·桥接模式