延续上一小节内容:下面继续讲解虚函数和多态

  1. 虚函数和多态
  1. 基类指针可以指向任何派生类的对象,但是不能调用派生类对象的成员。
  2. 但是,基类可以调用覆盖了虚函数的函数。(现在调用将来,这有问题,说明现在影响了将来。)
  3. 基类可以被继承,如果虚函数没有被实现,可以继续被下一个类继承。
  4. 当派生类没有能够覆盖虚函数的时候,若派生类的对象访问这个函数,那么此时将使用基类定义的函数。(现在调用过去,没有问题,已经定义过)

举例:

// BlankTest.cpp : 定义控制台应用程序的入口点。

//知识点:虚函数

//虚函数的强大之处在于能够预测未来。

//记住:基类指针可以指向任何派生类型的对象,但不能访问派生类型对象中定义的成员,但是可以调用虚函数(纯虚也可以)的实现函数。

#include "stdafx.h"

#include <iostream>

using namespace std;

 

class A

{

public:

    virtual void f()

    {

        cout << "我是虚函数 " << endl;

    }

protected:

private:

};

 

class B : public A

{

public:

    void f()

    {

        cout << "我派生自A " << endl;

    }

};

 

class C : public B

{

public:

    void f()

    {

        cout << "我派生自B"<< endl;

    }

};

 

class D :public A// 没有覆盖A中的虚函数,此时D的对象调用f这个函数的时候,将调用基类当中的函数。

{

public:

    void ff()

    {

        cout << "没有覆盖虚函数!" << endl;

    }

};

int _tmain(int argc, _TCHAR* argv[])

{

    A *p = new A();

    B b;

    C c;

    D d;

    p->f();

    p = &b;

    p->f();

    p = &c;

    p ->f();

    p = &d;

    p->f(); //基类指针可以调用虚函数的实现函数。即使它是派生类对象当中的成员。

    //p -> ff(); //基类指针没法调用派生类当中的成员。

    d.ff();

    return 0;

}

纯虚函数与抽象类

解释:含有一个或多个的纯虚函数的类叫抽象类。

特点:抽象类只能被继承不能被实例化。派生类必须覆盖这个纯虚函数,这个和虚函数有点不同,虚函数中,它的派生类不一定要必须覆盖。有时候,我们可以这样理解:

抽象类的派生类,才是我们需要的类,我们通过派生类,就可以利用基类的接口,调用基类的成员,而且可以基于派生类的不同而调用不同版本的虚函数的实现函数。

即:可以根据自己的需要,对纯虚函数重新定义,来满足自己的需要。

举例:

// BlankTest.cpp : 定义控制台应用程序的入口点。

//知识点:虚函数

//虚函数的强大之处在于能够预测未来。

//记住:基类指针可以指向任何派生类型的对象,但不能访问派生类型对象中定义的成员,但是可以调用虚函数(纯虚也可以)的实现函数。

#include "stdafx.h"

#include <iostream>

using namespace std;

 

class A

{

public:

    virtual void f() = 0 //纯虚函数

    {

        cout << "我是虚函数 " << endl;

    }

 

    void aa()

    {

        cout << "基函数的成员函数!" << endl;

    }

protected:

private:

};

 

class B : public A

{

public:

    void f()

    {

        cout << "我派生自A " << endl;

    }

};

 

class C : public B

{

public:

    void f()

    {

        cout << "我派生自B"<< endl;

    }

};

 

class D :public A// 没有覆盖A中的虚函数

{

public:

    void ff()

    {

        cout << "没有覆盖虚函数!" << endl;

    }

};

int _tmain(int argc, _TCHAR* argv[])

{

    B b;

    C c;

    //D d; //D没有实现纯虚函数,所以不能定义对象。

    b.f();

    b.aa();

    c.f();

    c.aa();

    return 0;

}

 

多态:

多态分为两种: 编译时的多态与运行时的多态。

而编译时的多态一般指早期绑定;运行时的多态指动态绑定。

早期绑定:函数的重载,函数的调用以及运算符重载。简单点说,就是在编译的时候就可以确定调用某一个函数了,这个函数是确定的。

动态绑定:一般指虚函数。即:运行时才能确定函数的调用。

 

  1. 预处理器先用编译器对源代码进行处理。

    主要有以下几种: #include #define #ifndef #if #else

    我们可以应用预处理器提高编程的效率。

    举例:

    // BlankTest.cpp : 定义控制台应用程序的入口点。

    #include "stdafx.h"

    #include <iostream>

    using namespace std;

     

    //#define DEBUG //通过这行可以决定 调试信息 的有无,这个比较好。赞一个。

    int _tmain(int argc, _TCHAR* argv[])

    {

    #ifdef DEBUG

        cout << "我在调试模式下!" << endl;

    #endif // _DEBUG

     

        cout << "我在运行模式下"<<endl;

        return 0;

    }

  2. C++运算符重载

    运算符重载和函数重载有异曲同工之妙,不同之处在于运算符重载,载的是构造类型的数据,基本数据类型的数据不需要重载。重载的目的是为了让运算更加简洁、明白。

    所谓的重载是对里面的运算符进行重新使用,而且只是针对这一种运算符,不是其他的。

    语法格式:

    返回类型 operator 单目运算符(参数列表)

    {

    //函数体

    }

    返回类型 operator 双目运算符(虚参1, 虚参2)

    {

    //函数体

    }

    注:对于双目运算符,两个虚参中至少得有一个是构造类型。

  3. C++命名空间

    所谓命名空间,你心里面想着文件夹的概念就OK了,主要用处就是为了避免冲突。

    比如,我在a文件夹下建立文件b,我也可以在c文件夹下建立文件b,但就是不能在 a 文件夹下,建立两个b。

    格式:

    namespace 命名空间名称

    {

    //函数体

    }

    而且,命名空间也要符合命名规范,所以对于命名空间名称我们也是可以起别名的,比如 namespace geography information system,我们可以简写为: namespace GIS = geography information system;

    以上只是一种使用别名的规范而已。

    Using 的作用:就是使当前文件夹下所有的函数名 暴露 在源程序中,这样我们就可以省略写 "命名空间名:: 使用到的名称或命令"。

    举例:

    // BlankTest.cpp : 定义控制台应用程序的入口点。

    #include "stdafx.h"

    #include <iostream>

    //using namespace std;

    using std::cout;

     

    //以下两个同名的函数:之所以不报错,是因为他们在不同的命名空间下。

    //#define DEBUG //通过这行可以决定 调试信息 的有无,这个比较好。赞一个。

    namespace zhu

    {

        void show()

        {

            cout << "我在zhu这个namespace下!" << std::endl;

        }

    }

    namespace xue

    {

        void show()

        {

            cout << "我在xue这个namespace下!" << std::endl;

        }

    }

    int _tmain(int argc, _TCHAR* argv[])

    {

    zhu::show();

         xue::show();

    #ifdef DEBUG

        cout << "我在调试模式下!" << endl;

    #endif // _DEBUG

     

        cout << "我在运行模式下"<< std::endl;

        return 0;

    }

命名空间和类联系在一起,珠联璧合,天下无敌。命名空间是类的一种有效的组织结构方式,我们用命名空间可以有效的将类进行分类管理,每个类有一个命名空间,这样我们在做大型程序开发时,可以为类库添加结构和层次的组织关系。

举例:

// BlankTest.cpp : 定义控制台应用程序的入口点。

#include "stdafx.h"

#include <iostream>

//using namespace std;

using std::cout;

 

//以下两个同名的函数:之所以不报错,是因为他们在不同的命名空间下。

//#define DEBUG //通过这行可以决定 调试信息 的有无,这个比较好。赞一个。

namespace zhu

{

    void show()

    {

        cout << "我在zhu这个namespace下!" << std::endl;

    }

}

namespace xue

{

    void show()

    {

        cout << "我在xue这个namespace下!" << std::endl;

    }

}

 

namespace kui

{

    class A

    {

    public:

        void show()

        {

            cout << "我是属于kui命名空间里面A类里面的函数!" << std::endl;

        }

    };

}

namespace kui1

{

    class A

    {

    public:

        void show()

        {

            cout << "我是属于kui1命名空间里面A类里面的函数!" << std::endl;

        }

    };

}

int _tmain(int argc, _TCHAR* argv[])

{

zhu::show();

     xue::show();

 

     kui::A a;

     a.show();

 

     kui1::A b;

     b.show();

#ifdef DEBUG

    cout << "我在调试模式下!" << endl;

#endif // _DEBUG

 

    cout << "我在运行模式下"<< std::endl;

    return 0;

}

C++学习总结 复习篇2的更多相关文章

  1. C++ 学习总结 复习篇

      友元的使用 分为友元类和友元函数     //友元类与友元函数的共同点:都可以让某一个类作为另一个类或者函数的参数.          //友元类:它让当前类成为另一个类的友元,然后,另一个类 ...

  2. NOIP复习篇

    NOIP复习篇---枚举 --------------------------------------------------------------------------------------- ...

  3. Java工程师学习指南 初级篇

    Java工程师学习指南 初级篇 最近有很多小伙伴来问我,Java小白如何入门,如何安排学习路线,每一步应该怎么走比较好.原本我以为之前的几篇文章已经可以解决大家的问题了,其实不然,因为我之前写的文章都 ...

  4. 数据库MySQL学习笔记高级篇

    数据库MySQL学习笔记高级篇 写在前面 学习链接:数据库 MySQL 视频教程全集 1. mysql的架构介绍 mysql简介 概述 高级Mysql 完整的mysql优化需要很深的功底,大公司甚至有 ...

  5. 一步步学习javascript基础篇(0):开篇索引

    索引: 一步步学习javascript基础篇(1):基本概念 一步步学习javascript基础篇(2):作用域和作用域链 一步步学习javascript基础篇(3):Object.Function等 ...

  6. 一步步学习javascript基础篇(3):Object、Function等引用类型

    我们在<一步步学习javascript基础篇(1):基本概念>中简单的介绍了五种基本数据类型Undefined.Null.Boolean.Number和String.今天我们主要介绍下复杂 ...

  7. Python3学习(3)-高级篇

    Python3学习(1)-基础篇 Python3学习(2)-中级篇 Python3学习(3)-高级篇 文件读写 源文件test.txt line1 line2 line3 读取文件内容 f = ope ...

  8. Python3学习(2)-中级篇

    Python3学习(1)-基础篇 Python3学习(2)-中级篇 Python3学习(3)-高级篇 切片:取数组.元组中的部分元素 L=['Jack','Mick','Leon','Jane','A ...

  9. Python3学习(1)-基础篇

    Python3学习(1)-基础篇 Python3学习(2)-中级篇 Python3学习(3)-高级篇 安装(MAC) 直接运行: brew install python3 输入:python3 --v ...

随机推荐

  1. Python 基本数据类型 (二) - 字符串

    str.expandtabs([tabsize]): str类型的expandtabs函数,有一个可选参数tabsize(制表符大小) 详细来说,expandtabs的意思就是,将字符串中的制表符\t ...

  2. JMeter学习笔记21-如何添加思考时间

    本文来介绍,JMeter如何插入思考时间.前面介绍过一个真实的性能测试场景,是需要加入思考时间,来模拟真实用户行为.本文就来介绍,如何在三个请求之间添加思考时间. 1. 在Test Plan下新建一个 ...

  3. 学习笔记3——WordPress文件目录结构详解

    **********根目录********** 1.index.php:WordPress核心索引文件,即博客输出文件.2.license.txt:WordPress GPL许可证文件.3.my-ha ...

  4. POJ-2594 Treasure Exploration,floyd+最小路径覆盖!

                                                 Treasure Exploration 复见此题,时隔久远,已忘,悲矣! 题意:用最少的机器人沿单向边走完( ...

  5. HDu-1247 Hat’s Words,字典树裸模板!

    Hat's Words 题意:给出一张单词表求有多少个单词是由单词表里的两个单词组成,可以重复!按字典序输出这些单词. 思路:先建一个字典树,然后枚举每个单词,把每个单词任意拆分两部分然后查找. 目测 ...

  6. Azure Storage Blob文件重命名

    Azure Storage的SDK并没有提供文件重命名的方法,而且从StorageExplorer管理工具里操作修改文件名的时候也有明确提示: 是通过复制当前文件并命名为新文件名再删除旧文件,不保存快 ...

  7. [luoguP4035] [JSOI2008]球形空间产生器(高斯消元)

    传送门 设球心的坐标为未知量 用最后一个点来表示球面到球心的距离,那么它和前n个式子相等 移项乱搞 最后高斯消元 #include <cmath> #include <cstdio& ...

  8. Mychael原创题 洛谷T23923 Mychaelの水题 【题解】

    原题链接 题目大意: 有来自三个地区的人各a,b,c位,他们排成了一排.请问有多少种不同类型的排法,使得相邻的人都来自不同的地区 \(a,b,c<=200\) 答案取模 题解 弱弱的标程解法 设 ...

  9. bzoj1063【Noi2008】道路设计

    题意:http://www.lydsy.com/JudgeOnline/problem.php?id=1063 用一种划分方式将树划为重链和轻链,使得所有点到根节点的路径经过的轻链最大值最小 sol: ...

  10. TeraTerm设定(窗体大小,字体字号)保存为默认值

    Tera Term是一款很好的SSH工具,大家经常遇到一个头疼的问题,每次打开的时候,都要自己重新设置一遍Font. 介绍一下把自己喜欢的字体,设置好后,保存到默认配置中的方法. 设置窗体大小: 设置 ...