类与对象是C++不同于C语言的一个板块,内容很多,笔者把这部分分为三篇博客来讲解,希望能够帮助各位读者更容易地理解这些知识点。弄清楚这一部分之后,C++就算是成功入门了。
C语言就是典型的面向过程语言,关注的是过程,分析问题的求解步骤,通过函数调用逐步解决问题。
面向对象的编程,主要关注对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。
对象可以用来模拟世界上任何一个实体,比如一个人,一辆汽车或者一个银行账户。以人来做例子,世界上有很多人,虽然世界上没有两个人是完全相同的,但是所有人之间都有一写共同的属性,比如名字、性别、身高等。在编程的时候,将这些共性抽取出来,定义为一个模板。为这个模板定义一个名字——类,它定义了一组具有相同属性(成员变量)和方法(成员函数)的对象,描述对象的共同特征和行为。
与C语言中存在的结构体不同,在类中,不仅可以定义变量,还可以定义函数。在C++中,使用class作为定义一个类的关键字。
class className
{
class body;//由成员变量和成员函数组成。
};
class作为定义类的关键字,className为类的名字,{}中为类的主体,注意类定义结束后存在一个不可省略的分号。 类体中的内容称为类的成员,类中的变量称为类的属性或者成员变量;类中函数被称为类的方法或者成员函数。
一般情况下,在学习的过程中采用第一种方式即可,在以后的项目或者工作中应该用第二种定义方式。
另外,还有一则定义成员变量的小Tips。
class Date
{
public:
void Init(int day)
{
day = day;
}
private:
int day;
int month;
int year;
};
能分清谁是形参,谁是真正的成员变量吗?所以,为成员变量取名字的时候,应该给它加上一个前缀或者后缀,以便区分。比如:
class Date
{
public:
void Init(int day)
{
——day = day;
}
private:
int _day;
int _month;
int _year;
};
面向对象有三大特性:封装、继承、多态。封装的核心概念是将数据(属性)和操作这些数据的方法(行为)捆绑在一起,并对外部隐藏对象的内部实现细节,只开放公共接口以供调用。封装本质上是一种管理,让用户更方便使用类。
C++实现封装的方式是:用类将对象的属性和方法结合在一块,让对象更加完善,通过访问权限,选择性的将接口提供给外部的用户使用。访问限定符允许开发者隐藏类的内部实现细节。通过限制对类成员的访问,可以防止外部代码直接修改对象的内部状态,从而保护对象的完整性。
C++有三种访问限定符:public(共有)、protected(保护)、private(私有)。对它们有如下说明:
类定义是一个新的作用域,类的所有成员都在类的作用域中。在类体外定义成员时,需要使用作用域解析运算符::。
#include
using namespace std;
class my_Class
{
private:
int _age;
int _sex;
public:
void print();
my_Class()
{
_age = _sex = 1;
}
};
void my_Class::print()//需要指定print属于my_Class这个类
{
cout << _age << " " << _sex << endl;
}
int main()
{
my_Class d;
d.print();
return 0;
}
前面说到,类是一群某些属性和方法相同的对象的抽象,是一个模板,将这个模板特殊化,用它来创建对象的过程被称为类的实例化。
class my_class
{
int _a;
int _b;
};
int main()
{
class d;
d._a = 1;
d._b = 1;
return 0;
}
一个类中,既有成员变量,又有成员函数,那么一个类的对象中包含了什么?怎么计算一个类的大小?
实际上,计算机只保存成员变量,而成员函数存放在公共的代码段。所以一个类的大小,实际就是该类中的成员变量之和。当然,在类中也存在着内存对齐的问题。你还记得什么是内存对齐吗?
#include
using namespace std;
class my_Class
{
private:
int _age;
int _sex;
public:
void print();
void my_Class_Init(int age, int sex)
{
_age = age;
_sex = sex;
}
};
void my_Class::print()
{
cout << _age << " " << _sex << endl;
}
int main()
{
my_Class d1,d2;
d1.my_Class_Init(1, 2);
d2.my_Class_Init(2, 4);
d1.print();
d2.print();
return 0;
}
上面的代码中,笔者实例化了两个对象。函数体中,没有关于不同对象的区分,那如果两个不同的对象调用同一个函数,函数是怎么知道该设置d1对象还是d2对象呢?
在这里,笔者想说的是,在计算机科学中是没有黑魔法的,计算机所有的东西都是人做出来的,别人能想到的,你也能想到,所有的东西,只是你现在不知道而已,只要你坚持下去,总有一天,你会把所有的细节都搞明白的。
这个问题也是如此,计算机中没有什么是凭感觉的,C++的编译器给每个非静态的成员函数增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),函数体中所有成员变量都是通过该指针去访问的。只不过所有的操作对用户都是透明的。在编写代码的时候,这一步只能由编译器帮我们完成。
需要注意的是: