“这个时刻来临了。”海象先生说。
“去讲述众多的事情:去讲述鞋子、船只和封蜡,去讲述卷心菜,还有国王们...“
------- 路易斯.卡罗尔《爱丽丝镜中奇遇记》
类,是C语言与C++最大的区别,这也是C++能做到面向对象编程的原因。
为了说明类,首先要讲明白什么是结构体,类有点类似于结构体的功能拓展,这也就使得能够自定义类的C++在编程方面优于C的原因(当然,这其中还有很多适配于类这个东西的其他技术,如类的继承、多态...)
结构体,形如
//定义一个人的结构体,其中包括姓名、性别、年龄、身高、体重信息
struct Human
{
string name;//要包含string类的头文件#include <string>
string gender;
int age;
double height;
double weight;
};//";"勿忘
注意这样几个问题:
1.结构体名一般首字母大写,结构体名可以是任何非关键字的词。
2.结构体定义形式:struct StructName{这里声明任何你想要给结构体的属性,我们称其为结构体成员变量member};//分号勿忘
3.结构体内成员访问方式 StructName.member,例如Human.name,使用点“.”操作符来访问
4.结构体一般不在函数内定义,这样之后的代码都可以使用,有点全局变量的意思。
5.不同的结构体可以有相同的成员变量命名,我们的访问成员变量的机制(structName.member),使得计算机不会找错变量。
6.如果有这样两个类型都是Human的结构体变量 Human_liming、Human_zhangwei,那么下面的赋值:
Human_liming=Human_zhangwei;
等价于:
Human_liming.name = Human_zhangwei.name;
Human_liming.gender = Human_zhangwei.gender;
Human_liming.age = Human_zhangwei.age;
Human_liming.height = Human_zhangwei.height;
Human_liming.weight = Human_zhangwei.weight;
7.函数参数传递可以使用结构体的传值调用也可以传引用调用。
8.结构体初始化,在结构体后直接赋值,方式如下:
Human InitHuamn = {liming,male,21,180.0,131.2};
赋值顺序必须和定义顺序一致,初始化值多余定义个数会报错,少于则不会,依次赋值后(如果类型一致的话),未被赋值的会自动初始化为该类型的默认值(默认值和当前被分配的内存有关,不要认为整形的自动初始化后是0)。尽量手动初始化,别给自己找麻烦。
类,形如:
#include<iostream>
#include<string>
class Human//定义一个人的类,其中包括姓名、性别、年龄、身高、体重信息,及一个名为speak的函数
{
public:
void speak();
std::string name;//要包含string类的头文件#include <string>
std::string gender;
int age;
double height;
double weight;
private:
};//";"勿忘
Human InitHuman = { "LiMing","male",23,181.0,131.1 };//建立一个对象并为其赋值。
int main()
{
InitHuman.speak();
return 0;
}
void Human::speak()//定义类成员函数
{
std::cout << "my name is " << name << std::endl;//成员函数内部调用成员变量不需要点操作符Huamn.name
}
类和结构体类似,不过在类内部不仅有成员变量,还有成员函数。
被定义为类这种类型的变量(准确的说是变量的值,无所谓,不论你指的哪一个都不影响理解)被称为对象。
一个对象包含数据和函数。当采用类这种方式编程时,一个程序可以看做是许多相互作用的对象的集合。这些对象之所以可以交互,是因为对象拥有行为(动作),对象的行为是通过调用对象的成员函数来体现的。这就是面向对象的编程中所说的对象。
这样理解可能会更直白,C语言由于结构体的限制,只能制作出一个死人墓碑,上面记载了他的各种信息(结构体将数据组合为数据),比如生辰八字、籍贯姓名、生平阅历...而C++用类可以制作出一个活人(类用数据和函数组合成对象),他不仅承载着这个人的信息,还可以让他做出一些行为(通过成员函数实现,如上面的说话speak)。
关于类注意以下几点:
1.类定一下的变量成为对象
2.类内有成员函数(不是必须)
3.定义类的成员函数时要包含类名,因为不同的类中可能存在同名的函数(这是被允许的)。方式(使用域操作符::)为:
returnType className::functionName(parameterList)
{
functionBody;
}
在成员函数内部使用成员变量不需要点“.”操作符。需要再说明的是,这里的不需要,不意味着用也对。实际上是不能用。因为只是在定义类的行为是怎样进行的。我们不知道会有那个对象来调用这个行为(函数),怎么对其进行对象.成员的限制呢?
如上面的代码,当InitHuman调用speak时,使用的成员变量自然就会被限定为InitHuman的。即InitHuman调用speak时,speak()内部cout的是InitHuman.name。
4.类也是一种类型,他的用法和C++预定义的int、double类型类似,我们可以向使用其他类型那样来使用类类型。其实string类就是一个以类定义的类型,他被包含在string.h头文件中。
怎样定义(封装)一个好的类,供别人使用?
和上篇文章中所说的如何封装一个函数供别人调用一样。类作为一种我们自己定义的类型,我们也希望不需要关注他的实现过程,类的操作,或者说类定一下的对象的行为,都是通过类的公有函数实现的,程序员在使用这些类时,无需关心成员函数的具体实现,他只需要了解成员函数的声明及成员函数的相关描述。(其实这里还是函数的封装问题)
面向对象编程最重要的原则之一就是封装--通过类来隐藏成员函数以及数据的实现细节,只暴露相关的使用接口。
实现类封装的一种方法就是将类中的成员函数定义为私有的private。private关键字后的成员都是私有的,表示我们不能在类外访问这些成员。(如果上面的例子中speak()定义在了private中,那么在main函数里就不能进行InitHuman.speak()的调用)
public定义的没有这种访问限制。
具体怎样定义一个好的类,还有很多的要求,这样做的好处也有很多。字太多直接上截图。
结构体和类究竟有什么区别呢?这个问题也是程序员面试时常被问到的一个问题。
结构体通常不包括成员函数,且其成员变量都是共有的。(C++中结构体也允许定义私有成员函数和成员变量,但一般我们不会这么做,别自找麻烦)
二者最大的区别就是:结构体成员变量如果没声明是公有还是私有时,默认是公有。而类中如果没有声明公私,默认私有。