学习笔记C++_3 类成员进阶

一. 类成员

1.1 空类

        空class定义的对象大小不能为0,实际为1字节,起到了一个占位作用,用来唯一标识,区分各个对象。

class CTest {};
    cout << sizeof(CTest) << endl;    //1

1.2 类成员属性

        类成员属性: 属于对象,只有在定义对象的时候,才会存在, 多个对象中存在多份,彼此独立,互不干扰,属性在对象被销毁也会被销毁。

class CTest {
public:
	int m_a;     //栈区
	CTest() { m_a = 0; }

	void show() { cout << m_a << endl; }
	void play() { cout << "play" << endl; }
};    
    
    CTest p, q;
	cout << &p.m_a << ' ' << &q.m_a << endl;
    //012FF8B8 012FF8AC

        对于堆来讲,生长方向是向下的,也就是向着内存地址增加的方向;对于栈来讲,它的生长方式是向上的,是向着内存地址减小的方向增长。

1.3 类成员方法

        类成员方法: 属于类的,编译期就存在,一个类中只会存在一份,多个对象共享这个函数, 他的存在与否和是否定义对象无关。

    CTest* pp = nullptr;    //指针并不是实际存在的
	pp->play();    //利用空指针调用成员函数

【C++】空指针调用成员函数及访问成员变量-CSDN博客

 二. this 指针

this 关键字 也是指针变量

是类中 非静态成员函数 中,隐藏的第一个参数,默认由编译器去添加

    void show(/* CTest* const this */) { 
		cout << m_a << endl; 
		cout << this->m_a << endl;

		play();
		this->play();
	}
	void play(/* CTest* const this */) { cout << "play" << endl; }

作用:在非静态成员函数中,使用其他成员(包括静态)时,都是通过this指针隐式调用的

类型:当前类对象的指针,类名* const this,指向了调用该函数的对象。作为对象和成员之间的连接桥梁,在函数中使用其他成员可以不用显式的写出this指针,让使用者无感知的使用this指针。

 构造函数和析构函数也会有隐藏的this指针

在《C++函数编译原理和成员函数的实现》一节中讲到,成员函数最终被编译成与对象无关的普通函数,除了成员变量,会丢失所有信息,所以编译时要在成员函数中添加一个额外的参数,把当前对象的首地址传入,以此来关联成员函数和成员变量。这个额外的参数,实际上就是 this,它是成员函数和成员变量关联的桥梁。

三. 静态成员

3.1 静态属性

 静态属性:不属于对象,也不会包含在对象之中。属于类,编译期存在,存在与否和是否定义对象无关。

调用:可以通过 类名作用域 直接调用静态成员,如果有对象的话,通过对象调用也是可以的。

#include <iostream>

using namespace std;

class CTest {
public:
	int m_a = 1;
	static int m_b;	//带有类内初始值设定项的成员必须为常量

	CTest() {
		m_a = 1;
		m_b = 4;	//赋值,更改值
	}

};

//静态成员属性,在类外定义 以及初始化,在类外应该省略static关键字
int CTest::m_b = 2;	

int main() {

	cout << CTest::m_b << endl;	//不通过对象直接调用
    //2
	CTest test;
	cout << sizeof(test) << " " << sizeof(CTest) << endl;	//4 4

	cout << test.m_a << ' ' << test.m_b << endl;	//1 4

}

一个类中存在一份的静态属性,多个对象共享这个静态成员。

    CTest test2;
	cout << &test.m_b << " " << &test2.m_b << endl;
	//0065C008 0065C008

无论静态放在哪,内存都在全局/静态区

3.2 静态成员函数

静态成员函数:属于类的,编译期存在,一个类只有一份,多个对象共享这同一份静态的成员函数。

调用: 可以通过 类名作用域直接调用静态成员,如果有对象的话,通过对象调用也是可以的。

与一般成员函数区别:
1. 静态函数没有隐藏的this指针参数
2. 静态函数只能使用静态的成员属性,一般的函数静态、非静态成员都可以使用。
3. 静态函数 通过类名作用域直接调用静态成员,一般函数不能通过类名作用域直接调用(必须通过对象调用)

    void fun();
	static void funStatic(/* 没有隐藏的this指针 */) {	//静态成员函数
		cout << "funStatic" << endl;
		//cout << this->m_a;	//ERROR:“this”只能用于非静态成员函数内部
		cout << m_b << endl;	//CTest::m_b
		fun2();	//可以调用其他静态成员函数
		//this->fun();	//ERROR:没有this没法调用一般的成员函数
	}
	static void fun2() {
		cout << "static fun2 " << endl;
	}

    
    CTest::funStatic();
	//CTest::fun();	//ERROR:非静态成员引用必须与特定对象相对

3.3 常量

3.3.1 初始化参数列表

初始化参数列表:在构造参数列表后,加上“:”后面是要初始化的成员名字,使用"()"进行初始化,才是一个严格意义上的初始化操作。普通的变量也可以在初始化参数列表中进行初始化(不可以对静态初始化),初始化多个成员,使用”,“分割。

class CTest {
public:
	int m_a;
	//声明
    const int m_b;    //定义了就要初始化,初始化后,不可修改,不可赋值

	//初始化参数列表:在构造参数列表后,加上“:”后面是要初始化的成员名字,使用()进行初始化
	//定义
    CTest():m_b(2) ,m_a(1){
		//m_b = 2;	//不允许赋值操作
	}
};

        初始化参数列表 初始化成员的顺序,取决于成员在类中声明的先后顺序。和写在初始化参数列表中的顺序无关 

	CTest(int v) :m_a(v),m_b(m_a) { }

3.3.2 常函数 

class CTest {
public:
	mutable int m_a;	//mutable可变的,指该变量在常函数中是可变的
	const int m_b;	 //定义了就要初始化,初始化后 ,不可修改、赋值

	//常成员函数,加在void 前是修饰返回值
	//const 修饰了this指针指向的对象,const 类名 * const this
	void fun( /* const CTest* const this */) const {
				//常量指针常量
		cout << m_a << ' ' << m_b << endl;
		//m_a = 10;	左值错误
		//this->m_a = 10;	const约束了this指针指向的对象,不能修改
		int* p = (int*)&m_a;    //注意:const int *类型的值不能用于初始化 int*类型的实体
		*p = 30;
		cout << m_a << ' ' << m_b << endl;
	}

};

const int *类型的值不能用于初始化 int* 类型的实体。因为若此操作合法,就可以直接用int*去修改const int*中的值,这样的话const就没有意义了。想要使用需要强转。

    int a = 0;
	const int b = 1;
	int* const p1 = &a;	//const 修饰了指针本身,指针的指向不能修改,但是指针指向的内容可以修改
	*p1 = 2;
	const int* p2 = &a;	//const 修饰了指针指向的内容,不能通过指针去修改内容,但是指针的指向可以改
	p2 = &b;

品析常成员函数,普通成员函数,静态成员函数之间的关系

	void fun1(/* const CTest* const this */) const {
		//fun2();	//this指针无法传递
		fun3();	//没有this不受影响
	}
	void fun2(/* CTest* const this */) {
		//fun2->this=fun1->this		//const int *类型的值不能用于初始化 int* 类型的实体
		fun1();
	}
	static void fun3() {

	}

同名同参的常函数和普通成员函数是重载,优先匹配普通,常量会优先匹配常函数。

静态函数和普通函数同名同参不可同时存在,因为没法区分

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值