面向对象三要素:封装继承多态的阐述及示例

  面向对象的三个基本特征是:封装、继承、多态。

一 封装

  封装就是将数据与操作数据的源代码进行有机的结合,形成类,其中数据和函数都是类的成员。隐藏了类的实现,类的使用者只需知道公共的接口,就可以使用该类;封装帮助防止意外的改变和误用;对程序调试有很大的帮助,因为改变类的成员变量只用通过公共接口。   谈到封装,就必然有类的存在。类类似结构体,但它更多功能和更灵活:

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;
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏云霄雨霁

Java--泛型的约束和局限性

1324
来自专栏烂笔头

Python魔术方法-Magic Method

目录[-] 介绍 在Python中,所有以“__”双下划线包起来的方法,都统称为“Magic Method”,例如类的初始化方法 __init__ ,Pyt...

3106
来自专栏WD学习记录

Python数据结构与算法笔记(2)

栈、队列、deques、列表是一类数据的容器,它们数据项之间的顺序由添加或删除的顺序决定。一旦一个数据项被添加,它相对于前后元素一直保持该位置不变。诸如此类的数...

761
来自专栏日常分享

Java 将两个有序数组合成为一个有序数组

   (2)将 两个数组 对应索引下的元素进行比较,小的一方 放入最终数组中的当前索引下的位置,并使小的一方数组的索引+1;

751
来自专栏从流域到海域

《Java程序设计基础》 第8章手记Part 2

第八章内容 Part 2 - … - 抽象类和抽象方法 - 接口及接口的实现 - 利用接口实现类的多重继承 - 内部库和匿名类 ...

1929
来自专栏ShaoYL

预处理指令(条件编译)

34611
来自专栏程序生活

Python itertools的使用简介无限迭代器chain方法

用*放在一个可迭代对象前面可以将对象拆分成多个单元素,比如first=[['1','2','3','4','4'],['2','4','2']],如果把*放在f...

491
来自专栏黑白安全

关于PHP语言在内存中的分配(堆和栈的区别)

本文以PHP语言为例来分析计算机中各段存储区的区别,代码段、堆空间段、代码段、初始化静态常量段。

1102
来自专栏无所事事者爱嘲笑

获取url参数的精简代码

1074
来自专栏老马说编程

(37) 泛型 (下) - 细节和局限性 / 计算机程序的思维逻辑

查看历史文章,请点击上方链接关注公众号。 35节介绍了泛型的基本概念和原理,上节介绍了泛型中的通配符,本节来介绍泛型中的一些细节和局限性。 这些局限性主要与Ja...

1876

扫码关注云+社区