面向对象的三个基本特征是:封装、继承、多态。
一 封装
封装就是将数据与操作数据的源代码进行有机的结合,形成类,其中数据和函数都是类的成员。隐藏了类的实现,类的使用者只需知道公共的接口,就可以使用该类;封装帮助防止意外的改变和误用;对程序调试有很大的帮助,因为改变类的成员变量只用通过公共接口。
谈到封装,就必然有类的存在。类类似结构体,但它更多功能和更灵活:
class Date //类的声明没有分配内存,只是说明了类的结构
{
public: //类的成员可以使用标识符来控制它们的可访问性
int year; //类的成员变量
int month;
void SetDate(int year,int month) //类的成员函数
{
this->year = year;
this->month = month;
}
}; //类的声明以分号结尾
为了使用类,可以声明一个该类型的变量:
Date today; //类的实例化
today.year = 2016; //类的一个实例,访问成员变量
today.month = 5;
today.SetDate(2016,5); //访问成员函数
接下来举个封装实现的例子:
class Change
{
private:
int m_value;
public:
int GetValue(){return m_value;}
void SetValue(int value){this->m_value=value;}
static int _num; //声明静态成员
};
int Change::_num = 0; //静态数据成员的真正定义
int main()
{
Change change;
change.SetValue(100);
cout << change.GetValue() << endl;
system("pause");
change._num++;
cout << change._num <<endl;
return 0;
}
备注:静态成员变量是属于类的本身,是所有对象的共享变量;它的值是保持修改的最新值;使用格式:类名::静态成员;初始化必须在类的代码文件中进行;声明为static的静态成员可以在类的范围内共享。
二 继承
继承是指可以使用现有类的所有功能,可以使一个对象直接使用另一个对象的属性和方法。通过继承创建的新类称为“子类”或者“派生类”,被继承的类称为“基类”或者“父类”。
class base{
public:
base(){
a = 0;
b = 1;
c = 2;
}
int a;
protected:
int b;
private:
int c;
};
// 接下来是三种继承方式
class derived1 : public base{//public继承
public:
void fun(){//derived class可以访问public和protected member
cout<<base::a<<base::b<<endl;
// cout<<base::c;//不能访问
}
};
class derived2 : protected base{//protected继承
public:
void fun(){//derived class可以访问public和protected member
cout<<base::a<<base::b<<endl;
// cout<<base::c;//不能访问
}
};
class derived3 : private base{//private继承
public:
void fun(){//derived class可以访问public和protected member
cout<<base::a<<base::b<<endl;
// cout<<base::c;//不能访问
}
};
class derived4 : public derived3{//base的member不能被private继承的派生类的子类访问
public:
void fun(){
// cout<<a;
}
};
class derived5 : base{//默认private继承
void fun(){//derived class可以访问public和protected member
cout<<base::a<<base::b;
// cout<<base::c;//不能访问
}
};
int main(void)
{
base b1;
derived1 d1;
derived2 d2;
derived3 d3;
d1.fun();
d2.fun();
d3.fun();
cout<<b1.a;//base class Object只能访问public member
cout<<d1.a;//public继承时 derived class Object只能访问base class的public member
//cout<<d1.b<<d1.c;//不能访问
//cout<<d2.a<<d2.b;//protected继承时 derived class Object不能问访base class的member
//cout<<d3.a;//private继承时 derived class Object不能问访base class的member
return 0;
}
三 多态
多态性可以简单地概括为“一个接口,多种方法”,程序在运行时才决定调用的函数,它是面向对象编程领域的核心概念。
C++多态性是通过虚函数来实现的,虚函数允许子类重新定义成员函数,而子类重新定义父类的做法称为覆盖(override),或者称为重写。重载则是允许有多个同名的函数,而这些函数的参数列表不同,允许参数个数不同,参数类型不同,或者两者都不同。编译器会根据这些函数的不同列表,将同名的函数的名称做修饰,从而生成一些不同名称的预处理函数,来实现同名函数调用时的重载问题。
多态有动态多态,静态多态,函数多态和宏多态。常说的多态是指动态多态,它是基于继承机制和虚函数来实现的。
宏多态的例子:
#define ADD{A,B} (A) + (B);
int main()
{
int i1(1),i2(2);
std::string s1("I,"),s2("am");
int i = ADD{i1,i2}; //两个整数相加
std::string s = ADD{s1,s2}; //两个字符串相加,连接
}
class A //父类
{
public:
void foo()
{
printf("1\n");
}
virtual void fun()
{
printf("2\n");
}
};
class B : public A //子类
{
public:
void foo()
{
printf("3\n");
}
void fun()
{
printf("4\n");
}
};
int main(void)
{
A a;
A *p = &a;
p->foo(); //本身是基类指针,指向的又是基类对象,
p->fun(); //调用的都是基类本身的函数,因此输出结果就是1、2。
p = &b; //基类指针指向子类对象,这就是多态
p->foo(); //指向的固定偏移量的函数,结果还为1
p->fun(); //指向虚函数,通过虚函数找到相应函数地址
return 0;
}