类的实现
类是C++的特性,一种数据类型,专用于面向对象编程中。
定义
C++中通常使用class 关键字定义一个类,类中定义了其对象包括什么(类成员属性),以及对象可以执行什么(类成员函数)
class 类名
{
//类体
访问限定符(public/protected/private):
类成员函数
类成员变量
};
例如,定义日期类
class Date
{
public:
void set(int year,int month,int day)
{
_year=year;
_month=month;
_day=day;
}
private:
int _year;
int _month;
int _day;
};
访问限定符
类在设计时,可根据需求,将类成员属性、函数等用权限加以控制。
类成员的访问限制是通过在类主体内部对各个区域标记 public、private、protected 来指定的。关键字 public、private、protected 称为访问修饰符。
访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止。
class M
{
public: //公有成员
protected: //受保护成员
private: //私有成员
};
公有权限 | public | 成员类内外都可以访问 |
受保护权限 | protected | 成员只能在类内访问 |
私有权限 | private | 成员只能在类内访问 |
class 和 struct的区别
class定义的类,默认访问权限为private;struct 定义的类,默认权限为public
类的实例化
用类创建对象的过程,可以称为类的实例化
一个类可以实例化多个对象,每个对象占用物理存储空间,但类本身不占用。
class Dog
{
private:
int _name;
int _old;
};
//实例化
int main()
{
Dog wangchai; //对象1
Dog xiaotian; //对象2
}
类对象的存储方式
我们对类对象的存储方式进行猜测,有以下3种猜想:
对象中包含类的各个成员

当同一个类,创建多个对象时,每个对象中都会保存相同的函数,而这些函数的代码都被各对象所保存,因此,这种存储方式会造成相同的代码被保存多次,浪费存储空间。
对象中包含类成员变量和类成员函数地址

只保存成员变量,成员函数放在公共代码段

class Person
{
public:
//非静态成员变量占用对象空间
int _ma;
//静态成员变量不占用对象空间
static int _mb;
//成员函数不占对象空间,所有成员函数共享一个函数实例
void func()
{}
};
类对象是以哪种方式存储的呢?通过VS2019测试后,得出结论:
一个类的大小,是它所有成员变量大小之和(注意内存对齐)。
当类为空类时,类大小为1字节
this指针
C++类中成员变量和成员函数是分开存储的,多个类对象会调用同一块代码。那代码是如何区分具体是哪个对象调用自己的呢?
this 指针解决了以上问题:
1.this指针指向了被调用成员函数所属的对象
2.this指针是隐含在被调用成员函数的形参中,不需要定义
3.this指针的类型为: 类类型* const

功能1:解决名称冲突
当形参和成员变量重名时,使用this指针

功能2:返回对象本身

this指针不能被随意更改,因此它是一个常量指针
空指针访问成员函数
C++中,空指针也是可以访问成员函数的,但是要注意this指针是否为空的情况
class Person
{
public:
void showClassName()
{
cout<< "This is Person class."<<endl;
}
void showPersonAge() //void showPersonAge(Person* this)
{
cout<<"age= "<<m_age<<endl; //等价于cout<<"age= "<<this->m_age<<endl;
}
private:
int m_age;
}
int main()
{
Person* p=NULL;
p->showClassName(); //正常运行
p->showPersonAge(); //err,传入this指针(p)为空,无法访问m_age
}
改进:
class Person
{
public:
void showClassName()
{
cout<< "This is Person class."<<endl;
}
void showPersonAge() //void showPersonAge(Person* this)
{
if(this==NULL)
{
return ;
}
cout<<"age= "<<m_age<<endl; //等价于cout<<"age= "<<this->m_age<<endl;
}
private:
int m_age;
}
int main()
{
Person* p=NULL;
p->showClassName(); //正常运行
p->showPersonAge(); //err,传入this指针(p)为空,无法访问m_age
}