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

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

一 封装

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

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 String 常量池的理解。

作为最基础的引用数据类型,Java 设计者为 String 提供了字符串常量池以提高其性能,那么字符串常量池的具体原理是什么,我们带着以下三个问题,去理解字符串...

982
来自专栏take time, save time

初级程序员面试不靠谱指南(三)

二、指针的好基友的& 1.&的意义。说&是指针的好基友其实不恰当,因为&这个符号在C/C++不止有一种含义,但是因为其经常会和指针一起出现在被问的问题列表上,所...

3179
来自专栏java一日一条

大公司最喜欢问的Java集合类面试题

java.util包中包含了一系列重要的集合类,而对于集合类,主要需要掌握的就是它的内部结构,以及遍历集合的迭代模式。

863
来自专栏java一日一条

Java Lambda 表达式学习笔记

Java Lambda 表达式是 Java 8 引入的一个新的功能,可以说是模拟函数式编程的一个语法糖,类似于 Javascript 中的闭包,但又有些不同,主...

381
来自专栏偏前端工程师的驿站

Java魔法堂:解读基于Type Erasure的泛型

一、前言                               还记得JDK1.4时遍历列表的辛酸吗?我可是记忆犹新啊,那时因项目需求我从C#转身到Jav...

2115
来自专栏赵俊的Java专栏

由一道 Java finally 执行顺序的题引发的思考

2054
来自专栏xingoo, 一个梦想做发明家的程序员

【面试虐菜】—— JAVA面试题(1)

今天参加笔试,里面有设计模式,和一些基础题! 印象最深的是:什么不是Object的函数,我蒙的finalize,哎,无知! 还问了,接口与抽象类的不同,还...

1819
来自专栏博岩Java大讲堂

Java泛型的学习和使用

3144
来自专栏java一日一条

JAVA集合类(大公司面试喜欢问的)

看了一些所谓大公司的Java面试问题,发现对于JAVA集合类的使用都比较看重似的,而自己在这方面还真的是所真甚少,抽空也学习学习吧。

822
来自专栏JavaEE

探讨Java参数传递问题

可能很多人都知道参数有形参和实参之分,却不知道区别到底是什么;知道Java中内存分为栈、堆、方法区等5片内存,不知道每片内存中保存的都是什么;关于参数的传递到底...

752

扫码关注云+社区