目录
前言:
类的定义:
类的访问限定符及封装:
限定符:
封装:
类的作用域:
类的实例化:
类对象的大小:
this指针:
this指针的特点:
总结:
前言:
就普遍而言,c语言在解决问题时讲究的是过程,而C++更关注问题中的对象。
就好比 “完成作业” 这个事件吧,c语言会关注 “写作业”,“上交给学委”,“学委整理作业”,“老师批改作业”,“分发作业”这样的过程。但是C++会关注“学生”,“学委”,“老师” 这样类似的对象。
而类呢,就相当于c语言中的结构体,类似于模板的功能,但是类的功能更加完善和全面。
好了,大概有个概念之后我们来看看具体的内容吧。
类的定义:
class为定义类的关键字,ClassName为类的名字,{}中为类的主体,注意类定义结束时后面分号。
类中的元素称为类的成员:类中的数据称为类的属性或者成员变量;
类中的函数称为类的方法或者成员函数。
类有两种定义方式:
1.声明和定义都在类中进行
//fun.h #includeusing namespace std; class Data { void Init() { _age = 0; } void Push() { cin >> _name >> _sex >> _age; } void Print() { cout << _name << " " << _sex << " " << _age << endl; } char _name[20]; char _sex[10]; int _age; };
2.声明放在.h文件中,类的定义放在.cpp文件中
//fun.h
class Data
{
void Init();
void Push();
void Print();
char _name[20];
char _sex[10];
int _age;
};
//fun.cpp
#include"fun.h"
void Data::Init() //要标明是哪个类的函数,即域 Data::
{
_age = 0;
}
void Data::Push()
{
cin >> _name >> _sex >> _age;
}
void Data::Print()
{
cout << _name << " " << _sex << " " << _age << endl;
}
那么类定义好了之后怎么用呢?
其实很简单,就像定义结构体变量那样:
实际操作一下来看看:
这里可以看出在使用时编译报错,“无法访问 private 成员” 这个信息告诉我们成员访问时会受到限制,这些成员都是private(私有)的,这里就涉及到了另外一块儿知识---类的访问限定符及封装
类的访问限定符及封装:
限定符:
如上文所提到的,限定符总共有三个:public(公有),private(私有),protected(保护)
所谓公有就是可供使用者在类外随便使用,而私有就是在类里可以使用,但在类外就没有使用权限了,且保护和私有类似。
注:class的默认访问权限为private,struct为public(因为struct要兼容C)
访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
对上面的类进行一些改动:
#includeusing namespace std; class Data { public: void Init(); void Push(); void Print(); private: char _name[20]; char _sex[10]; int _age; };
可以看到Push和Print函数都能正常使用了,但是_age仍不能被使用,原因在于我们把Init、Push、Print函数的访问权限开放了,而下面的三个变量仍是私有状态。
封装:
定义:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行 交互。
实际上我们可以这样理解,对于类里的数据和函数,有些是可以直接供他人自由使用的,但有东西些太自由地给别人使用会导致出现一些意料之外的、不符合设计者初衷的错误。因此就需要对这些数据和函数进行包装处理,有的给你权限,有的不给,且功能都是模块化,对外不展示细节操作。
这样做的好处很显然是方便管理和正确使用的,减少了一些意料不到的问题的产生。
类的作用域:
上面我们在定义和调用类函数时,会在前面加上作用域“Data::”,类的所有成员都在类的作用域中。在类体外定义成员,需要使用 :: 作用域解析符 指明成员属于哪个类域。
类的实例化:
上面我们定义好类的结构之后,紧接着就创建了一个对象“people”,这个过程就是类的实例化。
类的特点:
1. 类只是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储它
2. 一个类可以实例化出多个对象,实例化出的对象 占用实际的物理空间,存储类成员变量。
类对象的大小:
和计算结构体的方法一样,这里也要引入对齐数来进行计算。
但是,类对象里也有函数,那函数的大小也要计算在内吗?
由此我们根据实际代码来进行合理的推测:
int main()
{
// 类中既有成员变量,又有成员函数
class Data
{
public:
void Init();
void Push();
void Print();
private:
char _name[20];
char _sex[10];
int _age;
};
// 类中既有成员变量,又有成员函数
class A1 {
public:
void f1() {}
private:
int _a;
};
// 类中仅有成员函数
class A2 {
public:
void f2() {}
};
// 类中什么都没有---空类
class A3
{};
printf("A1:%dn", sizeof(A1));
printf("A2:%dn", sizeof(A2));
printf("A3:%dn", sizeof(A3));
printf("Data:%dn", sizeof(Data));
return 0;
}
从结果可以看出,函数是不计算进大小的。实际上,为了避免每次定义对象时都会重新定义函数,在定义类对象时只保存成员变量,成员函数存放在公共的代码段。 而一个类的大小,实际就是该类中”成员变量”之和,当然也要进行内存对齐,注意空类的大小,空类比 较特殊,编译器给了空类一个字节来唯一标识这个类。
this指针:
有细心的读者会发现前面的函数在定义和使用时,并没有传参。就比如Print函数,它需要用到三个成员变量,但是实际上看上去像是直接在使用了,其实不然,如果没有一些限制,那么当两个对象都调用Print函数时,到底使用的是谁的成员变量?
实际上C++中通过引入this指针解决该问题,即:C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有成员变量的操作,都是通过该 指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。
this指针的特点:
1. this指针的类型:类类型* const
2. 只能在“成员函数”的内部使用
3. this指针本质上其实是一个成员函数的形参,是对象调用成员函数时,将对象地址作为实参传递给this 形参。所以对象中不存储this指针。
4. this指针是成员函数第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递
例如:
void Print(Data* this)
{
cout << this->_name << " " << this->_sex << " " << this->_age << endl;
}
这里的this存的就是对象的地址;
总结:
由于是刚刚学习C++,可能有些地方讲的不是很清楚,若是有错误的地方还请大家多多包涵哈。
相应的问题欢迎在评论区里指出,拜拜~



