一:类的定义
(一)类的定义
(1)类的定义格式:
class name{
// 类成员变量
// 类方法(函数)
};
class是定义类的关键字,name为定义的类的名字,后面的花括号里面包含有两部分:成员变量和成员函数。
在c++中struct也可以定义类,有什么区别呢?
struct定义的类成员默认是public的,class定义的类默认是private的,struct照常可以定义结构体。
// 结构体
struct Stu {
string _name;// 前置_
float _height;// 后置_
int _ID;//m_
int _age;
};
// 学生类
struct Stu {
// 成员变量
string _name;
float _height;
int _ID;
int _age;
// 成员函数
string GetName()
{
return _name;
}
int GetAge()
{
return _age;
}
};
代码风格:为了使成员变量易于区分,通常在前面加_或者后面加_或者m_
class Stu {
string _name;// 前置_
float height_;// 后置_
int m_ID;//m_
int _age;
// 成员函数
string GetName()
{
return _name;
}
int GetAge()
{
return _age;
}
};
(二)访问限定修饰符
访问限定修饰符是为了限制规定用户对类的使用权限
访问限定符有三个:
public
private
protected
public修饰的成员在类外可以直接被访问;protected和private修饰的成员在类外不能直接被访问。
访问权限作⽤域从该访问限定符出现的位置开始直到下⼀个访问限定符出现时为⽌,如果后⾯没有访问限定符,作⽤域就到}即类结束。
class Stu {
private:
string _name;// 前置_
float height_;// 后置_
int m_ID;//m_
int _age;
// private作用位置到这里
public:
// 成员函数
string GetName()
{
return _name;
}
// 上一个public作用位置到这里
public:
int GetAge()
{
return _age;
}
};
代码风格:
⼀般成员变量都会被限制为private/protected,需要给别⼈使⽤的成员函数会放为public。
(三)类域
上一篇C到C++基础知识入门提到C++中域有函数局部域,全局域,命名空间域,类域。
这里的类域就是其一种。因为类域也有隔离,所以,如果要在外部定义类的成员时要在类里面添加上声明,在定义的时候加上类的域解析(函数返回值+类名+函数名+::)
// 定义一个栈的类
class stack {
//private:
public:
int _capacity;
int* _arr;
int _top;
public:
// 函数声明
void Init(int n = 4);// 缺省值给在声明里面
};
// 函数定义不在类里面就要使用::域解析运算符来定义
void stack::Init(int n)
{
_arr = nullptr;
_capacity = 0;
_top = 0;
}
int main()
{
stack st;
st.Init();
return 0;
}
二:对象——类的实例化
(一)对象的概念
(1)概念:对象是类的实例化,就像是一张设计图纸一样,根据图纸可以建造出很多的房子,而这里的房子就是对象,一张图纸可以建造出框架一样但是装修不一样的各式各样的房子,类和对象是一对多的关系。
(2)类也有空间,类在定义的时候就开辟了一段空间,遵从结构体内存对齐规则,它的大小在定义的时候就确定了。
(二)对象的大小
(1)对象和C的结构体一样,为了提高内存提取数据对的效率同样存从内存对齐规则。具体的内存对齐规则请看这篇文章结构体详解。
(2)对象只存储成员变量,不给成员函数分配空间,成员函数存储在代码段。
定义两个栈,有函数和没有函数大小都是一样的。
class stack {
int _capacity;
int* _arr;
int _top;
void init(int n)
{
_arr = nullptr;
_capacity = 0;
_top = 0;
}
};
class stack2 {
int _capacity;
int* _arr;
int _top;
/*void init(int n)
{
_arr = nullptr;
_capacity = 0;
_top = 0;
}*/
};
int main()
{
stack st;
stack2 st2;
cout << "有函数:" << sizeof(st) << endl;
cout << "没有函数:" << sizeof(st2) << endl;
return 0;
}
(3)当对象没有成员的时候,会给对象分配一个字节的空间。
class stack {
/*void Init(int n)
{}*/
};
int main()
{
stack st;
cout << sizeof(st) << endl;
return 0;
}
三:this指针
(1)定义:编译器编译后,类的成员函数默认都会在形参第⼀个位置,增加⼀个当前类类型的指针,叫做this指针。
(2)C++规定不能在实参和形参的位置显⽰的写this指针(编译时编译器会处理),但是可以在函数体内显⽰使⽤this指针
(3)this指针的定义:this指针是类类型的指针,默认使用const修饰,不可以修改,如:
this++;
这种是不行的
下面来看代码理解:
class Date {
private:
int _year;
int _month;
int _day;
public:
void init(int year, int month, int day) // 初始化
{
this->_year = year;
this->_month = month;
this->_day = day;
}
// 这里有一个影藏的this指针: void Print(Date* const this)
void Print()
{
//this++;——这种是不允许的
cout << this->_year << "/" << this->_month <<"/"<< this->_day << endl;
}
};
int main()
{
Date d1;
Date d2;
d1.init(2024, 06, 23);
d1.Print();// 这里其实是隐含的&d1:Print(&d1)
//这种是不允许的: d1.Print(&d1);不可以显示的使用
d2.init(2034, 07, 03);
d2.Print();// 同上,这里其实和C语言的函数传地址差不多
return 0;
}
this指针是成员函数的形参,所以也不存储在对象中,有些编译器会存放在寄存器里(vs),一些会随函数存放到开辟的函数栈帧里。
欢迎留言讨论指出不恰当或者不对的地方。