C++类与对象入门

声明与定义

在C++中【声明】(declaration)与【定义】(definition)是比较重要的两个概念,只有声明没有定义的类和函数是不可以使用的。【声明】只是告诉编译器有这么一个东西存在,但是没有给他分配内存。所以你即没有给他分配内存,又去使用他,那么就会报错误。

变量是一个比较特殊的存在。在Linux中,用的是g++编译器,他可能会自动给变量的【声明】自动分配内存,使用时就不会报错。但是在Windows,尤其是用Visual Studio编程的同学,用的是微软自家的编译器。这个编译器比较严格,不会给变量的【声明】自动分配内存。所以只要养成 【声明】了就一定要【定义】 的好习惯,那么不管在什么平台编程都不会出错。

到后面这个两个概念也会反复提到,所以别看这两个概念简单就忽视了。

int a = 10;		//变量的声明和定义
int b;			//变量的声明
b = 10;			//变量的定义

void fun();		//函数的声明
void fun(){...}	//函数的定义

class A;		//类的声明
class A {...};	//类的定义

面向对象编程(OOP)

如果之前学过C语言的同学,培养的编程思维应该是【面向过程】编程。这样的逻辑思维在刷题和解决问题方面没有什么问题,但是在大工程面前就会显得比较吃力。于是有人就提出了另外一种很好的编程方案,那就是【面向对象】编程(Object Oriented Programming)。

那什么是【面向过程】,什么又是【面向对象】呢?

举个例子:如何把大象放进冰箱里面?这个问题的答案肯定很多人都知道:打开冰箱->放入大象->关上冰箱。这就是一个很典型的【面向过程】的解决问题的思维,解决问题是从步骤下手的。如果是【面向对象】的思维,那么我会先抽象一个冰箱出来,这个冰箱能够打开和关闭,这是冰箱这个事物的能力;然后再抽象一个大象出来,这个大象可能会变大和缩小,这是大象这个事物的能力;那么解决这个问题就是:冰箱.打开->大象.缩小->冰箱.关闭。

可以看出【面向过程】更注重的是解决问题的过程,而【面向对象】更注重的是参与这个问题的事物是什么,他们有什么属性,他们能够干什么。 我们把这样的事物称之为“对象”(object)。

C++在C的基础上增加了面向对象编程的语法,使用起来十分具有灵活性。这篇文章只是简单的入门,以后我会用比较多的博文来更详细说明C++类与对象编程的一些细节。

面向对象的特点

  • 封装性
  • 继承性
  • 多态性

继承和多态是【面向对象】的最重要的两个特点,也他的最大优势。这些后期都会讲到,这里就大概感受一下什么是封装性吧。

类与对象

什么是类

这里引用百度百科的定义吧:

一个共享相同结构和行为的对象的集合。类(Class)定义了一件事物的抽象特点。通常来说,类定义了事物的属性和它可以做到的(它的行为)。举例来说,“狗”这个类会包含狗的一切基础特征,例如它的孕育、毛皮颜色和吠叫的能力。类可以为程序提供模版和结构。一个类的方法和属性被称为“成员”。

简单来说类就是一个模板,通过这个模板可以刻画出许多拥有相同基础特征的不同事物。

在C++中,我们将类的属性称作类的成员变量,将类的方法称作类的成员函数

什么是类的实例化

说完类的定义,我们来说说类的实例化。说到底,“狗”是一个抽象的概念,而隔壁老王家的哈士奇波比是个具体的存在。我们说波比是“狗”这个概念的一个实例,或者说波比是“狗”这个类实例化的一个对象。

类的声明与定义

我们先来定义一个游戏角色类,看以下代码:

class Character {
	int hp;
	int mp;
};

学过C语言的同学不难看出来,这不就是struct嘛。对没错,C++的class就是用struct来实现的,而且和struct没什么区别。唯一的区别就是,class定义好之后,如果不特定标明属性或者方法是公有的(public)还是私有的(private),那就都默认是私有的,而struct默认是公有的。(还有一个protected属性是跟继承有关的,以后再说)

公有和私有

公有和私有也很好理解:公有就是我可以用,别人也可以用;私有就是除了我自己之外别人都不可以用。放在类与对象里面理解就是:类实例化了一个对象,这个对象的公有成员变量你可以在任何地方任何时刻修改,但是私有成员变量只能由对象自己来修改。

优化一下以上代码:

class Character {
private:
	int hp;
	int mp;
	
public:
	void heal(int heal_hp){ hp += heal_hp; }
};

这里我把角色的hp和mp给私有化了,以保证外部不能随意修改他们的值。然后我定义了一个公有的函数heal,用于给角色恢复生命值,这样外部就可以通过调用这个成员函数来改变角色的hp。这就是封装,我不希望别人能够随意玩弄我角色,你只能用我规定的方法来玩弄他。

构造函数

我们在创建角色的时候,总得先给这个角色一些初始的数值吧,而且上面也说了只有【声明】没有【定义】是有可能会出问题的。构造函数就是干这事的,他在类被实例化的时候被调用:

class Character {
private:
	int hp;
	int mp;
	
public:
	//这是编译器自动补充的构造函数,但是如果自己实现了,编译器就不会自动合成了
	//Character(){};	
	Character() {
		//函数名必须和类名相同,并且没有返回值
		hp = 100;
		mp = 50;
		cout << "新建英雄成功!" << endl;
	}
	void heal(int heal_hp) { hp += heal_hp; }
};

对其进行实例化:

Character mario = Character();	//新建英雄成功!
Character link;					//新建英雄成功!

但是我们还希望我们的角色的hp和mp由我们自己来决定,那么就可以用到我上一篇博客说的函数重载了:

public:
	//这是编译器自动补充的构造函数,但是如果自己实现了的话,编译器就不会补充了
	//Character(){};
	Character() {
		//函数名必须和类名相同,并且没有返回值
		hp = 100;
		mp = 50;
		cout << "新建英雄成功!" << endl;
	}
	Character(int hp, int mp) {
		//this指针,用于指向实例化的对象
		this->hp = hp;
		this->mp = mp;
		cout << "新建英雄成功!!!" << endl;
	}
Character mario = Character(999, 999);	//新建英雄成功!!!
Character link(999, 999);				//新建英雄成功!!!

总结

入门介绍先到这里,本篇的主要目的不是深入的探讨,而是在于建立面向对象编程的认知。更深更细的东西我会在下一篇博文专门挑出来说的,也会再次谈到构造函数的。

我刚开始学面向对象编程的时候,一直有一个困惑,那就是我既然是要修改或者访问类里面的属性值,我为啥不直接将他设为public,这样不是更方便。为何要大费周章地专门写一个set函数去修改,专门写一个get函数去获取。后来在我看了浙江大学翁恺老师的C++面向对象课程之后,翁恺老师的解释令我恍然大悟。

他说将成员变量封装起来相当于把肌肉包在皮肤里面,我们可以通过大脑去控制肌肉的收缩,但是我们不会说拿一个电线,把电线接到肌肉上面去,通过电流让肌肉收缩。这个是可以实现,但是没有人会去这么做,太危险了。类的封装也是一个道理。

希望这个解释,也能帮助有和我一样困惑的同学。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值