关于面向对象编程对于一个java程序员那是再熟悉不过了,不过对于C++而言相对java还是有很多不同点的,所以全面复习一下。

C++ 在 C 语言的基础上增加了面向对象编程,C++ 支持面向对象程序设计。类是 C++ 的核心特性,用户定义的类型。

咱们来新建一个头文件来定义一下类:

其访问修饰符具体含义如下:

  • private:可以被该类中的函数、友元函数访问。 不能被任何其他访问,该类的对象也不能访问。

  • protected:可以被该类中的函数、子类的函数、友元函数访问。 但不能被该类的对象访问。

  • public:可以被该类中的函数、子类的函数、友元函数访问,也可以被该类的对象访问。

其中构造函数和析构函数目前还木有实现,其实可以在声明的时候就定义实现,如下:

也可以在cpp中进行实现,新建一个cpp文件:

咱们来使用一下它:

编译运行:

其中类的析构函数是类的一种特殊的成员函数,它会在每次删除所创建的对象时执行(不需要手动调用)。

另外如果想通过构造方法来给成员变量赋值,当然可以跟java一样如下弄:

但是在cpp中还有它独特的地方就是在声明构造时就可以给成员变量进行赋值,表现如下:


此时实例化就得传两个参数了:

常量函数

函数后写上const,表示不会也不允许修改类中的成员。下面来看看:

声明一个给成员变量赋值的方法,没啥问题,但是!!如果给这个函数的后面加一个const修饰,情况就不一样啦,如下:

其错误提示为:

比较简单,也就是如果发现该函数只能读不会写,则可将其声明为常量函数。

友元 

类的友元函数是定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类,在这种情况下,整个类及其所有成员都是友元。

  • 友元函数
    这个是有别于Java的,假如咱们想通过这个函数来修改类中的私有成员,如下:

    此时就需要将这个函数声明为友元函数,具体做法如下:

    此时方法就不报错了:

    咱们来使用一下:

    编译运行:

  • 友元类
    下面来声明一个友元类:

    此时就可以将Teacher声明为Student类中的友元类,如下:

    也就是当Teacher声明为Student的友元类时,则Teacher中所有的函数及成员都是Student中的友元了。

静态成员

和Java一样,可以使用static来声明类成员为静态的,当我们使用静态成员属性或者函数时候 需要使用 域运算符 ::,下面咱们以单例模式为例:

在头文件中声明一个Instance类:

其中需要注意的是,对于静态成员是需要进行初始化的,可以在头文件中声明时就初始化,也可以在.cpp中进行,这里以cpp的方式来对成员变量进行初始化,如下:

下面来具体实现getInstance()方法:

我们知道对于Java来说这样写是会有线程安全问题,那对于C++11编译器来说会保证内部静态变量的线程安全的, 当然可以加锁,关于多线程的问题在之后会学习到,这里先不管多线程的情况,下面来使用一下这个单例:

重载函数

C++ 允许在同一作用域中的某个函数运算符指定多个定义,分为函数重载运算符重载

  • 函数重载
    这个跟java一样,所以举个例子既可:
  • 操作符重载
    这个是C++独有的,C++允许重定义或重载大部分 C++ 内置的运算符 ,函数名是由关键字 operator 和其后要重载的运算符符号构成的 ,重载运算符可被定义为普通的非成员函数或者被定义为类成员函数
    成员函数:
    新建一个头文件:

    假设要实现这样的一个操作,如下:

    接下来操作符重载就是将不可能成为可能,具体做法如下:

    此时定义了+号运算符重载之后,之前的对象相加操作就可以正常啦,看下结果:

    但是!!!有一个疑问:我们在操作符重载是在栈上申请的一块空间,那出了方法应该就会被回收,如下:

    那为啥我们还能在表达式中看到正常的结果呢?

    这是因为对于这个表示式底层是存在对象拷贝操作的,如下:

    那何以见得呢?咱们可以先定义一个拷贝函数来打印一下是否如猜想:

    所以定义一个无参的构造方法:

    此时咱们来运行看一下是否调用了两次拷贝构造:

    呃~~翻车了么?其实是因为:

    由于程序是在mac上跑的,可见是对返回值是做了RVO优化,从而是看不到拷贝构造函数的调用了。 总之记住一点:本来是要进行两次对象拷贝的,但是编译器做了一些优化最终会减少或者完全看不到对象的拷贝迹象了。

    非成员函数:
    新声明一个类:

    接着来声明操作符重载,这里不需要定义到Test2类的内部了,直接在我们调用的外部中来声明,如下:

    然后运行看一下结果:

    其中允许重载的运算符如下:

    比如说重载new、delete如下:

    void *operator new (size_t size)
    {
    cout << "新的new:" << size << endl;
    return malloc(size);
    } void operator delete(void *p)
    {
    //释放由p指向的存储空间
    cout << "新的delete" << endl;
    free(p);
    }

继承

跟java一样,类也是存在继承的,范例:

class A:[private/protected/public] B

默认为private继承

A是基类,B称为子类或者派生类

下面来看下具体代码:

那下面来使用一下:

此时涉及到继承的访问修饰符了,由于默认情况下是private继承,所以既使父类的方法是public的子类也无法访问,要访问就得将继承修饰符改一下:

其中涉及到继承修饰符如下:

方式 说明
public 基类的public、protected成员也是派生类相应的成员,基类的private成员不能直接被派生类访问,但是可以通过调用基类的公有和保护成员来访问。
protected 基类的公有和保护成员将成为派生类的保护成员
private 基类的公有和保护成员将成为派生类的私有成员

另外有一点是跟java不同的,java只支持单继承,而c++是支持多继承的,如下:

下面来看一下打印:

此时调用子类的test()会打印啥呢?如下:

而如果子类想调用父类的方法该如何写呢?

编译运行:

那如果将子类的test()方法删掉又会怎样呢?

从错误提示来看是因为在父类中定义有多个test()方法,咱们删掉其中一个基类的test()方法:

此时就正常了,再次编译运行:

从这个就可以看出为啥刚才报基类有多个test()的异常,是因为如果子类没有实现父类的方法,那么就会调用父类的,但是父类定义了两个test()方法,所以编译器不知道调哪个了,所以就报错了。

多态

多种形态。当类之间存在层次结构,并且类之间是通过继承关联时,就会用到多态。

静态多态(静态联编)是指在编译期间就可以确定函数的调用地址,通过函数重载模版(泛型编程)实现,那下面来举个例子来体会一下静态多态的表现:

此时打印的是:

动态多态(动态联编)是指函数调用的地址不能在编译器期间确定,必须需要在运行时才确定 ,通过继承+虚函数 实现,下面来看下:

其调用方式不变:

编译运行:

此时就调用的真正类型的方法,基于此,有下面一个原则:

构造函数任何时候都不可以声明为虚函数。

析构函数一般都是虚函数,释放先执行子类再执行父类,如果不声明为虚函数,则在多态中只会调用父类的析构函数了。

另外还有一种纯虚函数,其意义跟java中的abstract抽象方法类似,具体如下:

此时如果运行就会报错:

也很容易理解,跟java的一样,纯虚函数是一定需要在子类中进行实现的,如下:

此时编译就不报错了。

模板

模板是泛型编程的基础

  • 函数模板【类似于java中的泛形方法】

    函数模板能够用来创建一个通用的函数。以支持多种不同的形參。避免重载函数的函数体反复设计。

    下面来使用一下:

    其中有个等价的写法:

  • 类模板【类似于java中的泛型类】

    为类定义一种模式。使得类中的某些数据成员、默写成员函数的參数、某些成员函数的返回值,能够取随意类型

    常见的 容器比如 向量 vector 或 vector 就是模板类

    下面来看下代码如何写:

基本上跟java类似~

ndk学习之c++语言基础复习----面向对象编程的更多相关文章

  1. ndk学习之C语言基础复习----虚拟内存布局与malloc申请

    在这一次中来学习一下C语言的内存布局,了解它之后就可以解释为啥在用malloc()申请的内存之后需要用memset()来对内存进行一下初始化了,首先来了解一下物理内存与虚拟内存: 物理内存:通过物理内 ...

  2. ndk学习之c++语言基础复习----C++容器、类型转换、异常与文件流操作

    继续来复习C++,比较枯燥,但是这是扎实掌握NDK开发的必经之路,不容小觑. 容器: 容器,就是用来存放东西的盒子. 常用的数据结构包括:数组array, 链表list, 树tree, 栈stack, ...

  3. ndk学习之C语言基础复习----基本数据类型、数组

    关于NDK这个分类在N年前就已经创建了,但是一直木有系统的记录其学习过程,当然也没真正学会NDK的技术真谛,所以一直也是自己的一个遗憾,而如今对于Android程序员的要求也是越来越高,对于NDK也是 ...

  4. ndk学习之c++语言基础复习----C++线程与智能指针

    线程 线程,有时被称为轻量进程,是程序执行的最小单元. C++11线程: 我们知道平常谈C++线程相关的东东基本都是基于之后要学习的posix相关的,其实在C++11有自己新式创建线程的方法,所以先来 ...

  5. ndk学习之C语言基础复习----结构体、共用体与C++开端

    自己实现sprintf功能: 关于C中的系统函数sprintf在上次[https://www.cnblogs.com/webor2006/p/7545627.html]学习中已经用到过了,这里再来回顾 ...

  6. ndk学习之C语言基础复习----指针、函数、预处理器

    指针: 指针乃C.C++的灵魂之所在,所以有必要好好的复习复习.什么是指针?一句话来概括:“指针是一个变量,它的值是一个地址.”,其中指针变量的声明有如下三种形式: 其中第一种是被推荐的写法. 其中还 ...

  7. 2018.3.5 Java语言基础与面向对象编程实践

    Java语言基础与面向对象编程实践 第一章 初识Java 1.Java特点 http://www.manew.com/blog-166576-20164.html Java语言面向对象的 Java语言 ...

  8. MySQL学习笔记_8_SQL语言基础复习

    SQL语言基础复习 一.概述 SQL语句注释方式 1)以"#"开头直到行尾的所有内容都是注释 2)以"--"(--后还有一个空格)开头直到行尾的所有内容都是注释 ...

  9. GO学习-(19) Go语言基础之网络编程

    Go语言基础之网络编程 现在我们几乎每天都在使用互联网,我们前面已经学习了如何编写Go语言程序,但是如何才能让我们的程序通过网络互相通信呢?本章我们就一起来学习下Go语言中的网络编程. 关于网络编程其 ...

随机推荐

  1. csu 1770: 按钮控制彩灯实验

    1770: 按钮控制彩灯实验 Submit Page   Summary   Time Limit: 1 Sec     Memory Limit: 128 Mb     Submitted: 341 ...

  2. 守卫者的挑战(据说在bzoj有但我没找到)

    芒果君:一看就是概率dp(可是我不会啊,就算再裸也不会啊).然后先从最后想,能够满足题意的状态是 挑战次数>=L,获得价值>=0,那一定有f[总挑战数i][挑战成功数j][价值k].转移很 ...

  3. kafka连接报错kafka.errors.NoBrokersAvailable: NoBrokersAvailable

    问题: 本地windows系统远程连接kafka报错,kafka.errors.NoBrokersAvailable: NoBrokersAvailable. 解决: 在网上看到说是hosts文件需要 ...

  4. C#传递参数调用exe程序

    今天公司让我把Winform程序里的一块单独成一个exe文件,从原程序中打开新的exe程序,这就涉及到参数的传递,故来记录下传递参数到exe程序的方式 第一种方式 首先在程序A中添加引用using S ...

  5. C++程序设计学习-第2章

    第二章 变量与基本类型 1.基本内置类型 C++定义了一套包括算术类型和空类型在内的基本数据类型 算术类型:整型和浮点型,包括带符号类型(signed)和无符号类型(unsigned),带符号类型可以 ...

  6. python爬虫框架scrapy 豆瓣实战

    Scrapy 官方介绍是 An open source and collaborative framework for extracting the data you need from websit ...

  7. 软件模拟IIC实现EEPROM

    ....妈的太难.    反正就是控制引脚的高低电平 实现数据的读取....参考 I2C的协议层和物理层的那个几个图,个个信号产生的电平 自己看源码去把. 头疼

  8. Fabric分支/版本切换问题

    (以下示例是从 release-1.4 切换到 release-1.3) 首先将 $GOAPTH/src/github.com/hyperledger/ 下1.4版本的fabric-samples给删 ...

  9. STM32之ADC实例(基于DMA方式)

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/zouleideboke/article/details/75112224 ADC简介: ADC(An ...

  10. 部署java应用的几种方式

    J2EE应用 该应用根目录下有好多文件夹和以jsp结尾的文件 部署时,需要在tomcat的conf目录下的server.xml文件中添加上<Context path="/" ...