ndk学习之c++语言基础复习----面向对象编程
关于面向对象编程对于一个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++语言基础复习----面向对象编程的更多相关文章
- ndk学习之C语言基础复习----虚拟内存布局与malloc申请
在这一次中来学习一下C语言的内存布局,了解它之后就可以解释为啥在用malloc()申请的内存之后需要用memset()来对内存进行一下初始化了,首先来了解一下物理内存与虚拟内存: 物理内存:通过物理内 ...
- ndk学习之c++语言基础复习----C++容器、类型转换、异常与文件流操作
继续来复习C++,比较枯燥,但是这是扎实掌握NDK开发的必经之路,不容小觑. 容器: 容器,就是用来存放东西的盒子. 常用的数据结构包括:数组array, 链表list, 树tree, 栈stack, ...
- ndk学习之C语言基础复习----基本数据类型、数组
关于NDK这个分类在N年前就已经创建了,但是一直木有系统的记录其学习过程,当然也没真正学会NDK的技术真谛,所以一直也是自己的一个遗憾,而如今对于Android程序员的要求也是越来越高,对于NDK也是 ...
- ndk学习之c++语言基础复习----C++线程与智能指针
线程 线程,有时被称为轻量进程,是程序执行的最小单元. C++11线程: 我们知道平常谈C++线程相关的东东基本都是基于之后要学习的posix相关的,其实在C++11有自己新式创建线程的方法,所以先来 ...
- ndk学习之C语言基础复习----结构体、共用体与C++开端
自己实现sprintf功能: 关于C中的系统函数sprintf在上次[https://www.cnblogs.com/webor2006/p/7545627.html]学习中已经用到过了,这里再来回顾 ...
- ndk学习之C语言基础复习----指针、函数、预处理器
指针: 指针乃C.C++的灵魂之所在,所以有必要好好的复习复习.什么是指针?一句话来概括:“指针是一个变量,它的值是一个地址.”,其中指针变量的声明有如下三种形式: 其中第一种是被推荐的写法. 其中还 ...
- 2018.3.5 Java语言基础与面向对象编程实践
Java语言基础与面向对象编程实践 第一章 初识Java 1.Java特点 http://www.manew.com/blog-166576-20164.html Java语言面向对象的 Java语言 ...
- MySQL学习笔记_8_SQL语言基础复习
SQL语言基础复习 一.概述 SQL语句注释方式 1)以"#"开头直到行尾的所有内容都是注释 2)以"--"(--后还有一个空格)开头直到行尾的所有内容都是注释 ...
- GO学习-(19) Go语言基础之网络编程
Go语言基础之网络编程 现在我们几乎每天都在使用互联网,我们前面已经学习了如何编写Go语言程序,但是如何才能让我们的程序通过网络互相通信呢?本章我们就一起来学习下Go语言中的网络编程. 关于网络编程其 ...
随机推荐
- CentOS 7 命令
常用命令 文件与目录操作 命令 解析 cd /home 进入 ‘/home’ 目录 cd .. 返回上一级目录 cd ../.. 返回上两级目录 cd - 返回上次所在目录 cp file1 file ...
- CNN-4: GoogLeNet 卷积神经网络模型
1.GoogLeNet 模型简介 GoogLeNet 是2014年Christian Szegedy提出的一种全新的深度学习结构,该模型获得了ImageNet挑战赛的冠军. 2.GoogLeNet 模 ...
- Win10 彻底关闭 Windows Defender
1.使用快捷键 WIN+R 调出运行工具,然后再输入组策略命令 gpedit.msc 再点击确定. 2.进入组策略在计算机配置下面的管理模板,Windows 组件就可以看到 Windows Defen ...
- ubuntu中不能使用终端的情况
跟着网上的步骤去升级了一波python3,可谓一波未平! 当我将ubuntu中自带的python3.5升级3.6时,突然发现一个问题,怎么终端打不开了,于是去百度,找到一个博主的笔记,和我的情况一模一 ...
- Jupyter修改工作目录(Anaconda环境)
Anaconda安装时未添加环境变量 1.打开Anaconda Prompt 输入jupyter notebook --generate-config (base) C:\Users\Sroxi> ...
- Django Simple Captcha的使用
Django Simple Captcha的使用 1.下载Django Simple Captcha django-simple-captcha官方文档地址 http://django-simple- ...
- C#基础算法题 找出最大值和最小值
找出最大值和最小值 题目要求 输入n个数,n<=100,找到其中最小的数和最大的数 实现代码 using System; namespace _1.求最大最小 { class Program { ...
- asp.net core-2.在vs2017中创建asp.net core应用程序
今天我们用vs2017创建一个asp.net core 的应用程序,打开vs2017 点击:文件—>项目,选择asp.net core web 应用程序 点击确定 红框内就昨天用控制台去创建的应 ...
- MySQL5.7主从同步配置
主从同步,将主服务器(master)上的数据复制到从服务器(slave). 应用场景 读写分离,提高查询访问性能,有效减少主数据库访问压力. 实时灾备,主数据库出现故障时,可快速切换到从数据库. 数据 ...
- QMap里面的值任然是一个QMap,在做循环插入的时候需要记得清空。
这个问题是我以前的一个问题,当时由于有其他的事情去处理就忘记了,前段时间我的项目要进行集成测试了,为了避免这个缺陷,只能再把这个问题想起来了,再进行解决.有很多问题你觉得不应该发生,其实很多时候都是逻 ...