使用对象进行编程是C++的核心,也是我们常说的C++比C“高级”的重要根据之一。
但是不希望大家因为这样就对这个看起来很深奥的概念望而生畏。。。
所以要明确的告诉大家:对象的本质上不过是一种新的数据类型,只不过它拥有无限的潜力。。。|
打个比方就像再美丽的女孩本质上不过也是女,只不过她拥有无限的选择。。。
我们从一个类开始,首先类是一个模型。当我们为这个类创建实例的时候,也就是对象本身。这跟我们之前讲解的定义和使用结构的过程很相似,但是这更有扩展性和前瞻性。
对于初学者而言,我们先给大家一个区别:对象的内部可以有变量和函数,而结构通常只由名种变量构成。
我们知道,要找对象,内心先要有对象的模型不然怎么知道你找到后是猪还是牛?
创建简单的类
因此,我们首先需要知道的一件事情是如何编写一个简单对象的模型-类
类(Class)就像是一副蓝图,它决定一个对象将是什么样的(具备什么样的属性、功能)。
所以OOP过程的第一步是创建一个类,而每个类跟变量一样都有一个名字,我们就从如何声明一个类说起:
class MyFirstClass { };
就这样,我们创建了一个类!虽然它什么都干不了,但它是一个起点,一个成功的开始。
注意,类名的第一个字母采用大写是一种习惯的上的标准,但不是硬性规定。还有在类声明末尾,必须有一个分号,这一点跟C++结构情况相同。
类由变量和函数组成,对象将使用那些变量来存储信息,调用那些函数来完成操作。所以人们常常会看到一些专门术语:类里边的变量成为属性,函教成为方法。注意,他们的本质没有改变。
让我们来造辆车:
class Car { public: std::string color; std::string engine; float gas_tank; unsigned int Wheel; };//先动手,别等咯~
我们需要在声明变量之前先写出单词“public:" ,稍后我们将对此做法的理由作出解释!
刚刚我们声明了一辆车的简单属性,现在我们应该让他能跑起来吧?那么我们应该为类定义一些方法,其实也就是定义一些函数罢了。创建个人函数也是两个步骤的过程:先创建函数的原型(声明),再描述该函数本身实现过程。
给类添加方法如出一辙:先在类的声明里创建一个方法的原型,稍后再实现这个方法。
class Car { public: std::string color; std::string engine; float gas_tank; unsigned int Wheel; void fill_tank( float liter ); // 方法的声明:方法是”加油”,参数是”公升” };
现在我们的 Car类有了一个名为fillTank的方法,它只有一个输入参数,不需要任何返回值。 但是我们只有他的原型(声明),想要使用它,我们还需要对这个函数进行正式的定义(即告诉系统如何去实现它)。 方法的定义通常安排在类声明的后面:
void Car::fillTank(float liter) { gas_tank += liter; }
我们发觉作用域解析操作符(::),作用是告诉编译器这个方法存在于何处,或者说是属于哪一个类。 其实我们对这个不应该感到陌生,从一个开始就不提倡using namespace std;这样偷懒的做法,所以我们是std::cout。。。
事实上std::cout所引用的是std里定义的cout,而std::string数据类型其实也是一个对象。我们一直在使用对象,只是自己还不知道罢了。
#include <iostream> #include <windows.h> #define FULL_GAS 85 class Car { public: std::string color; std::string engine; unsigned int gas_tank; unsigned int wheel; void setColor(std::string col); void setEngine(std::string eng); void setWheel(unsigned int whe); void fillTank(int liter); int running(void); void warning(void); }; void Car::setColor(std::string col) { color = col; } void Car::setEngine(std::string eng) { engine = eng; } void Car::setWheel(unsigned int whe) { wheel = whe; } void Car::fillTank(int liter) { gas_tank += liter; } int Car::running(void) { std::cout << "我正在以120的时速往前移动。。。越过那高山越过那河。。。 "; gas_tank--; std::cout << "当前还剩 " << 100*gas_tank/FULL_GAS << "%" << "油量! "; return gas_tank; } void Car::warning(void) { std::cout << "WARNING!!" << "还剩 " << 100*gas_tank/FULL_GAS << "%" << "油量!"; } // 这辆车还是存在一些BUG,你能够发现它并DEBUG它吗? int main() { char i; Car mycar; mycar.setColor("WHITE"); mycar.setEngine("V8"); mycar.setWheel(4); mycar.gas_tank = FULL_GAS; while( mycar.running() ) { if( mycar.running() < 10 ) { mycar.warning(); std::cout << "请问是否需要加满油再行驶?(Y/N) "; std::cin >> i; if( 'Y' == i || 'y' == i ) { mycar.fillTank(FULL_GAS); } } } return 0; }
Pay attention:
面向对象编程技术(object-oriented programming)可以说是面向过程技术(procedural programming)的替代品。 面向过程技术关注的是对数据进行处理的过程,OOP技术关注的是对数据进行怎样的处理。 对象与结构有很多相似之处,但前者还可以有它们自己的函数。记住这点区别对掌握OOP技术的要领很有帮助。
有些程序员喜欢把类的声明和类的函数的定义分别存入两个不同的文件,前者存入.h头文件,后者存入相应的.cpp文件。这点今后我们会讨论。
C++允许在类里声明常量,但不允许对它进行赋值:
class Car { public: const float TANKSIZE = 85; // 出错 }
绕开这一限制的方法就是创建一个静态常量:
class Car { public: static const float FULL_GAS = 85; }
这种做法还有其他更高明的含义,以后我们将逐步介绍给大家。
类似于使用结构的情况,可以在声明某个类的同时立刻创建一些该类的对象:
class Car { 。。。。。。 } car1, car2;
这种做法在C++里是允许的。但作为一种良好的编程习惯,应该避免这种做法!
最后,假设我们有以下代码:
Car car1, car2;
car1.setColor(“WHITE”);
。。。。。。
car2 = car1;
把一个对象赋值给另一个同类的对象将会自动使同名的属性有同样的值。