第六章:面对对象
1、多态
例子:
足球运动员,他在射门时可能产生以下多种结果:
球射在门框上
求射到了观众席
球进了
我们把这种不同的对象(不同的足球运动员)调用相同名称的函数(射门),却可导致不同的行为或者结果的现象称为多态性。
2、类、对象、成员
例:
硬盘是个类,希捷硬盘是该硬盘类的一个对象。型号、容量和转速是该类的数据成员;读取数据、写入数据是该类的方法成员,又叫成员函数;数据成员和成员函数称为该类的成员,对象拥有并且可以封装这些成员,未经该对象许可,其他对象不可访问和修改该对象的成员。
3、类、对象、和成员的使用方法及区别
声明一个类
声明一个类后,我们才能使用它
例:
class Human {
public:
void GetStature ();
void GetWeight ();
private:
int stature;
int weight;
};
定义一个对象
Human Mike;
对象和成员的关系
用点运算符.来访问该对象的数据类型
不要给类赋值:如Human.weight=100;这样是错误的。
4、
例
#include <iostream>
using std::cout;
class Human {//使用class来声明一个类
public:
void walk() {cout<<"走路\n";}//分号不可省
void speak() {cout<<"说话\n";}
void run() {cout<<"跑\n";}
};
void main() {
Human mike;
mike.run();
mike.speak();
mike.walk();
//return 0;这样是错误的,因为main是void,改成int就可以了
}
5、private、public
将上面的public注释后,会出错。因为类的成员默认为私有,私有成员不能被对象直接访问,只能通过在类中设置的接口函数来间接访问私有成员。
例:
#include <iostream>
using std::cout;
class Human {//使用class来声明一个类
int t;
public:
void read(int w) {t=w;}//分号不可省
int print() {return t;}
};
int main() {
Human mike;
mike.read(3);
cout<<mike.print();
return 0;
}
一般情况下,我们可将类的数据成员设置为私有,而使用类的共有函数来访问他们。
6、如果将成员函数的声明和定义分开写
例;
#include <iostream>
using std::cout;
class Human {//使用class来声明一个类
int t;
public:
//void read(int) {t=w;}//分号不可省
void read(int);
int print() {return t;}
};
int main() {
Human mike;
mike.read(3);
cout<<mike.print();
return 0;
}
void Human::read(int w) {
w = t;
}
特别注意分号。
6、内联函数
1)普通内联函数
编译器为函数在内存中建立一个指令集,在反复调用这个函数,它跳转到这个指令集,然后再回去,调用过多的话,跳转很多,影响效率。c++中为解决这个问题,使用关键字inline声明函数,如:inline int func();
编译器不会创建真正的函数,而是将这代码复制到调用的地方。这样会增大程序的体积,但效率会高。
内联函数有显式声明和隐式声明之分。
内联函数只是在函数被频繁调而且代码简单是才使用。在不知道具体怎么操作时,最好不要使用,完成程序后,可以根据情况进行优化。
2)内联成员函数
显式:
#include <iostream>
using std::cout;
class Human {//使用class来声明一个类
int t;
public:
//void read(int) {t=w;}//分号不可省
inline void read(int);
//int print() {return t;}
inline int print();
};
int main() {
Human mike;
mike.read(3);
cout<<mike.print();
return 0;
}
void Human::read(int w) {
w = t;
}
int Human::print() {
return t;
}
隐式:
#include <iostream>
using std::cout;
class Human {//使用class来声明一个类
int t;
public:
void read(int w) {t=w;}//分号不可省
int print() {return t;}
};
int main() {
Human mike;
mike.read(3);
cout<<mike.print();
return 0;
}
这就是声明和定义分离的成员函数和声明和定义合并的成员函数的区别。声明和定义合并的成员函数是隐式的内联函数。所以应该看使用情形才可用。
7、头文件与源文件
我们可以将类的声明和定义保存在一个文件中,一般是扩展扩展名.h的文件;将程序执行部分存放在一个文件里,一般是.cpp文件,这样就可以在.cpp文件的顶端写代码,使头文件.h与.cpp相关联,代码如下:#include *.hpp;
*是给该文件起的名字,该行语句的意思是将*.h写入cpp文件中。
8、const成员函数
如果不想让某个成员函数修改成员变量的值,那么定义为const成员函数
例;void print() const{count<i*j;}
但是如果将下面的函数定义为const函数,报错,因为试图改变。
void func(int x,int y)const{i = x;j = y;}
9、构造函数
在创建某个类的对象时,由于对该对象的状态(数据)不是很明确,因此需要对其进行初始化。比如,长方体。构造函数是 rectangle(int l,int w){length = l;width=w;},着就相当于在创建一个长方体之前先确定长和高。
构造函数没有返回值。
10、默认构造方法
11、析构函数
析构函数用于在对象销毁后清除它占有的内存空间,也就是说他可以清除由构造函数创建的内存。
例
class A {
~A() {};//;类A的析构函数
}
析构函数;与类名相同、波浪号、不能有返回值、不能有参数、一个类只能有一个析构函数。
例:
#include <iostream>
using std::cout;
using std::endl;
class A {
public:
A();
~A();
};
A::~A() {cout<<"析构函数执行完毕\n";}
A::A() {cout<<"构造函数执行完毕\n";}
int main () {
A a;
return 0;
}
对象创建就会调用构造方法。
程序结束时,对象a的生命也自然终止,这是编译器会自动调用该类的默认析构方法来释放掉该对象占的内存。
12、析构对象数组
加入我们要一次声明很多的对象,那么可以将这些对象放在一个数组中来声明,例:
A a[3];
三个对象a[2] a[1] a[0]
例:
#include <iostream>
using std::cout;
using std::endl;
class A {
public:
A();
~A();
};
A::~A() {cout<<"析构函数执行完毕\n";}
A::A() {cout<<"构造函数执行完毕\n";}
int main () {
A a[2];
return 0;
}
执行两次构造方法,程序结束后,又执行两次析构方法。
13、总结
在面对对象编程中,类时最基本的数据类型,而对象时该数据类型定义出来的变量。
当定义某类的对象时,会自动调用该类的构造方法。当该对象的寿命结束时,又会自动调用析构函数来回收他所占用的内存。