c++之类和对象——类的定义,存储方式,this指针!(五千字长文详解!)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c++之类和对象——类的定义,存储方式,this指针!(五千字长文详解!)相关的知识,希望对你有一定的参考价值。

c++详解之类和对象——类的定义,存储方式,this指针!

面向过程和面向对象初步认识

面向过程:分析出求解问题的步骤,通过函数调用逐步解决问题

面向对象:关注的是对象!讲一件事分成不同的对象,靠对象的交互之间的完成的!(至于怎么实现就不用管)

类的引入

封装

类的访问限定符!

访问限定符可以让我们允许类里面的内容是否被别人访问,也可以更好的保护数据

在c语言中,我们虽然可以使用接口去访问增删查该结构体里面的数据,但是我们也是可以直接的对结构体里面的数据进行访问!这对于一个公共大型项目来说是很不好的!不能保证有谁不会乱修改

c++里面我们使用了访问限定符,对于我们不愿被别人直接修改的数据,我们直接不允许进行访问,只可以调用接口去对数据进行!

//其实struct也是可以的,不过我们一般都是使用class!
//class里面默认是私有的!
//struct里面默认是共有的!
class stack

private://私有部分——只能在类里面访问
	int* _a;
	int _size;
	int _capacity;
public://共有部分——类的内外都可以访问
	void Init(stack* st)
	
		_a = NULL;
        _capcity = 0;
        _size = 0;
	
    void Push(stack* st)
    
        //.....
    
;
//在类中数据类型不分上下可以在上面也可以在下面!不像C语言中一样一定要先在上面声明定义! 
class stack

public:
	void Init(stack* st)
	
		_a = NULL;
        _capcity = 0;
        _size = 0;
	
    void Push(stack* st)
    
        //.....
    
private:
	int* _a;
	int _size;
	int _capacity;
;
int main()

    stack ST;
    //ST._a;报错!   

访问限定符总结总结

  1. public修饰的成员在类外可以直接被访问
  2. protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)
  3. 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
  4. 如果后面没有访问限定符,作用域就到 即类结束。
  5. class的默认访问权限为private,struct为public(因为struct要兼容C)

注意:访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别

类的作用域

class student

public:
	void printstduent();
private:
	int _age;
	char _name[20];
	int _id;
;
//我们要指定printstudent是属于student这个类域里面的!
//因为不同的类域可能有相同名字的成员函数!
void student::printstduent()

	cout << _name << " " << _id<< " " << _age << endl;


class test

public:
	int _a;
	int _b;
	int test_(int c, int d)
	
		cout << c << " " << d;
	
;
int main()

    //既然它是一个作用域那么我们能不呢像命名空间一样用域作用限定符来访问呢?
    test:: _a = 10;//不能
    test:: test_(10,20);//不能
    //原因我们后面解释

类的实例化

类是对对象进行描述的,是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没 有分配实际的内存空间来存储它;比如:入学时填写的学生信息表,表格就可以看成是一个类,来描述具体学生信息

一个类可以实例化出多个对象,实例化出的对象占用实际的物理空间,存储类成员变量

class test

public:
	int _a;
	int _b;
	int test_(int c, int d)
	
		cout << c << " " << d;
	
;//这个类定义没有占用实际内存空间
//相当于一个图纸
int main()

    test a;//类的实例化!——相当于将图纸里面的东西给实现出来,这才占用了内存空间!
    test b;
    test c;
    //....        
    //回到上面的 test:: _a = 10;
    //因为没有实例化!根本没有占用内存空间!所以也就无法进行定义,修改,赋值!
    //命名空间能够访问是因为命名空间只是个已经存在的东西加了一堵墙!
    return 0;

类和对象的存储方式

==其实当类被定义的时候,只是其成员变量没有去占用内存空间,而成员函数此时已经被定义好然后放在公共代码段了!==

class test

public:
	int _a;
	int _b;
	int test_(int c, int d)
	
		cout << c << " " << d;
	
;
int main()

    test:: test_(10,20);//那既然如此为什么这个代码运行的时候仍然会报错呢?
    //成员变量是因为没有实例化而没有占用空间,但是为什么这个成员函数已经定义了却仍然无法使用?

结构体内存对齐规则

  1. 第一个成员在与结构体偏移量为0的地址处。
  2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。 注意:对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。 VS中默认的对齐数为8
  3. .结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。
  4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整 体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

this指针

class Date
 
public:
 void Init(int year, int month, int day)
 
 _year = year;
 _month = month;
 _day = day;
 
 void Print()
 
 cout <<_year<< "-" <<_month << "-"<< _day <<endl;
 
private:
 int _year;     // 年
 int _month;    // 月
 int _day;      // 日
;

int main()

    Data d1;
    d1.Init(2002,9,21);
    Data d2;
    d2.Init(2002,9,22);
    d1.Print();
    d2.Print();

 void Print()
 
 cout <<_year<< "-" <<_month << "-"<< _day <<endl;
 

//编译器修改后
 void Print(Date* const this)//添加this指针是编译器的工作,我们不可以去自己添加!
 
 cout <<this->_year<< "-" <<this->_month << "-"<< this->_day <<endl;
 
//this* const 为了防止我们把指针改了!const用于保护指针本身不被修改!


//所以对象进行调用的时候其实就是一个传参的过程!

    d1.Print(); // = Print(&d1);
    d2.Print();// = Print(&d2);
//但是我们不可以主动去传参
    d1.Print(&d1); 
    d2.Print(&d2);
//这样写是不行的!这是编译器的工作!
//这样就最终回答了上面的疑问

 //test:: test_(10,20);这个无法直接调用的原因是因为缺少了一个this指针参数!但是我们又没有办法去传,这就导致了报错!

但是我们可以在类里面使用this指针!

class Date

public:
	void Init(int year, int month, int day)
	
		_year = year;
		_month = month;
		_day = day;
	
	void Print()
	
		cout << this << endl;//当调用的时候我们可以看出d1,d2的地址
		cout << this->_year << "-" << this->_month << "-" << this->_day << endl;
        //我们也可以手动的添加上this指针的解引用!但是我们一般不怎么做,因为编译器会自动添加上!
	
private:
	int _year;     // 年
	int _month;    // 月
	int _day;      // 日
;
int main()

    Data d1;
    Data d2;

    d1.Print();
    d2.Print();

this指针的特性

  1. this指针的类型:类类型* const,即成员函数中,不能给this指针赋值。

  2. 只能在“成员函数”的内部使用

  3. this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给 this形参。所以对象中不存储this指针

  4. this指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传 递,不需要用户传递

this指针可以为空吗?

// 1.下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行
class A

public:
	void Print()
	
		cout << "Print()" << endl;
	
private:
	int _a;
;
int main()

	A* p = nullptr;
	p->Print();
	return 0;

// 1.下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行
class A

public:
	void PrintA()
	
		cout << _a << endl;
	
private:
	int _a;
;
int main()

	A* p = nullptr;
	p->PrintA();
	return 0;


以上是关于c++之类和对象——类的定义,存储方式,this指针!(五千字长文详解!)的主要内容,如果未能解决你的问题,请参考以下文章

C++之类和对象

《c++从0到99》 二 类和对象 上

《c++从0到99》 二 类和对象 上

C++类和对象

C++ 类与对象(上)

C++初阶:类和对象(上篇)类的定义 | 类的访问限定符及封装 | 类的作用域 | 类的实例化 | 类对象模型 | this指针