文章目录

  • inline内联函数
  • 虚函数
    • virtual 虚函数
    • virtual 纯虚函数和抽象类
  • c++ 中的struct
  • explicit (显式)
  • friend 友元函数与友元类
  • enum枚举
  • template 模板
  • C++11 variadic templates
  • try throw catch 异常

预处理 编译 汇编 链接
预处理: 宏替换,删掉注释,头文件的添加到一个文件中等等
编译: 将预处理后的 .i 文件进行一系列语法分析,词义分析,语义分析等等生策划那个.s 文件

inline内联函数

  1. 作用:内联函数是为了解决c语言中表达式形式的宏定义来解决程序中函数调用的效率问题,
  2. 产生的原因:c语言中表达式形式用宏来定义,但是宏是在预处理阶段被处理的,就只是简单的替代,并没有替换类型的检查,等等一系列操作,调用宏并不会产生额外的空间和时间的操作,效率会更高一点,但是宏 不能访问类的私有成员 宏也非常容易产生二义性 宏在预处理阶段不会进行参数的检查 。所以C++就使用了inline函数来解决这个事情,让编译器处理这个inline函数,编译器可以对语法语义等进行分析
  3. 内联函数与普通函数的区别
    普通函数: 如果main函数调用一个a函数,系统会先跳到a函数入口地址 -> 执行函数体 再返回到原函数调用的地方继续执行
    内联函数: 如果函数调用一个内联函数, 函数不需要进行寻址的过程,会直接将函数copy过来,执行函数体
    所以内敛函数的使用不需要寻址,进而提高了函数的效率
    但是这个拷贝阶段是在什么时候进行的呢,在编译阶段直接进行拷贝(内联)
  4. 内联函数与宏的区别,除了处理阶段不同外,内联函数实际上是一个函数,有返回值,参数列表,函数体,而宏只是一般的表达式
  5. 内联函数可以是虚函数么?虚函数可以是内联函数,内联可以修饰虚函数,当虚函数表现多态性的时候不能内联
    内联函数是在编译器阶段进行函数内联,但是虚函数的多态性是在运行期间,编译器并不能直到运行期间运行哪个代码,因此虚函数表现是多态的时候不可以内联
  6. C++中,类中的函数体默认是inline函数(隐式定义内敛函数)
  7. 一般小于十行的时候使用内联函数

虚函数

virtual 虚函数
  1. 为了实现C++的多态,C++使用了一种动态绑定的技术,这个技术的核心就是虚函数表(虚表)
    每个虚函数的类都有自己的虚拟表vptr(一个包含虚函数的基类有自己的虚表,继承了这个基类的派生类也拥有自己的虚表,因为派生类也需要实现这些虚函数),是在编译阶段编译器设置的静态指针数组(只有虚函数才拥有虚表,抽象类中的一般函数不拥有虚表),需要注意的是,同一个类的所有对象只需要一个虚表,继承了拥有虚函数的类的类也拥有自己的虚表

  2. 虚函数的参数默认值
    基类默认覆盖子类的默认值。参数并不是动态绑定的,而是根据调用者的类型决定的,虚函数调用的是子类的方法,方式参数默认的是基类的

class Base{public:virtual void fun(int x=10){cout<<"Base::fun(),x="<<x<<endl;}
};class Derived: public Base{public:virtual void fun(int x=20){cout<<"Derived::fun(),x="<<x<<endl;}
};int main()
{Derived d1;  //d1.fun();Base *bp=&d1;bp->fun();   //Derived::fun(),x=10return 0;}

bp是基类Base* 类型,参数调用的是Base的参数,静态绑定,但是因为指向的是d1 也就是Derived派生类,由于动态绑定的原因,会直接调用Derived::fun()
虚函数还是不要写默认参数比较好
3. 构造函数不可以是虚函数,构造函数的目的是用于初始化实例的,创建一个对象是需要明确对象的类型的,如果构造函数时虚函数,虚函数是在运行时确定对象的类型的,在编译阶段,编译器如果不知道对象的类型对象是无法被创建成功的。
4. 基类的虚函数可以是私有的,但要把main函数设置成是友元函数
当基类的虚函数是公有的,继承类实现的虚函数是私有的也是可以的

class Base{private:virtual void fun()   //虚拟类{cout<<"Base Fun"<<endl;}friend int main();   //友元函数
}; class Derived: public Base{public:void fun()    //虚拟类的实现   但是虚拟类是私有的{cout<<"Derived Fun"<<endl;}
};int main()
{Base *ptr=new Derived;ptr->fun();return 0;
}
virtual 纯虚函数和抽象类

虚函数: virtual
纯虚函数:声明赋值为0
抽象类:包含纯虚函数的类
1.抽象是没有实现的类, 所以抽象类不能直接创建对象(Base bp是错的),只能作为基类来产生派生类, 这个派生类必须要实现所有纯虚函数才能成为非抽象类(但是派生类可以不用实现所有的虚函数,纯虚函数一定要是实现)

1.定义抽象类
2.定义派生类:抽象类{实现抽象类中的纯虚函数}
3.定义派生类的对象

2.抽象类定义的指针和引用指向由抽象类派生出来的类的对象

Base *bp = new Derived();   //抽象类Base的指针变量bp指向他派生出来的类Derived
bp->show();
  1. 如果派生类没有实现抽象类中的纯虚函数,那么派生类也也会变成抽象类
  2. 抽象类可以有构造函数,构造函数不能是虚函数,但是析构函数可以是虚函数
    当基类指针指向派生类对象并删除对象时,我们可能希望调用适当的析构函数。 如果析构函数不是虚拟的,则只能调用基类析构函数,这会导致派生类的对象析构不完全
    使用delete调用析构函数
class Base {public:Base()   //构造函数{cout<<"constructor: Base"<<endl;}virtual ~Base()    //虚析构函数{cout<<"Destructor: Base"<<endl;}virtual void func()=0;   //纯虚函数};class Derived: public Base{public: Derived(){cout<<"Constructor:Derived"<<endl;}~Derived(){   cout<<"Destructor:Derived"<<endl;}void func()   //实现纯虚函数{cout<<"In Derived.func()"<<endl;}
};int main()
{Base *var=new Derived();delete var;return 0;
}
  1. 构造函数时初始化的,不能被对象调用

c++ 中的struct

  1. 可以在struct中定义数据,函数,使用访问修饰符(public, protected, private),还有继承
  2. 使用结构体的时候可以不带struct
  3. 如果结构体的名字与函数名相同,可以正常调用与运行,但在定义结构体的变量时候只能用带struct的
    但如果一个名字A被用于一个结构体的别名,是不能定义名字为A的函数的
  4. struct与class
    class可以看成一个对象的实现体,struct是一个数据结构的实现体
    class默认是private的,struct默认是public的

explicit (显式)

作用:
修饰构造函数,可以防止隐式转换和复制初始化
修饰转换函数,可以防止隐式转换,但是按语境转换除外

friend 友元函数与友元类

友元 提供了一种 普通函数(友元函数)与类的成员函数(友元类)
作用: 可以访问一个类中的私有private或者protect
注意: 友元关系没有继承性,没有传递性

enum枚举

template 模板

模板: 是具有相同特性的函数或者类的再抽象,模板是一种参数多态性的工具,模板并不是一个实实在在的函数或者类,仅仅是一个函数或者类的描述,是参数化的函数和类,分为函数模板和类模板

1.class表示T是一个类型参数,可以表示任意类型,例如int,double,struct, enum, class之类的数据类型,class也可以使用typename替代
2.但某些场合下,模板是不适用于特定的场合的,所以需要将模板特化
template<> 是模板特化的关键字 <>中不需要任何关键字

template <class/typename T1, class/typename T2,...> 返回类型 函数表 (参数表)
{函数模板定定义体
}//example
template<class T>
T Max(T a, T b)
{return (a>b)?a:b;
}//模板特化    将T使用特定的类型代替
template<> char * Max <char *>(char *a, char *b)
{return (strcmp(a,b)>=0)?a:b;
}
  1. 在同一个程序中,还有同名的普通函数,普通函数可以进行隐式的类型转换,模板以及特化函数不能够进行任何形式的类型转换
  2. 调用顺序:完全匹配的给模板函数 完全匹配的模板函数 类型相容的非模板函数
const int Size=5;template<class T>
void Array<T>::Sort()
{int p;for(int i=0;i<Size-1;i++){p=i;for(int j=i;j<Size;j++){if (a[p]<a[j])p=j;}T t=a[p];a[p]=a[i];a[i]=t;}
}//类模板的实例化  就是把class替换成具体的类型
template<>
void Array<char *>::Sort()
{int p;for(int i=0;i<Size-1;i++){p=i;for(int j=i;j<Size;j++){if (a[p]<a[j])p=j;}T t=a[p];a[p]=a[i];a[i]=t;}
}

C++11 variadic templates

try throw catch 异常

异常是程序在执行期间产生的问题,C++是指在程序运行时发生的特殊情况
异常提供了一种转移程序控制权的方式
throw:当问题出现时,程序会抛出异常
catch:在想要处理问题的地方,通过异常处理程序捕获异常
try:try是包括了一个或多个可能引发异常的语句

void temperature(int t)
{if(t==100)throw "It is at the boiling point.";else if(t==0)throw "It reached the freezing point.";elsecout<<"the temperature is OK..."<<endl;
}int main()
{try{temperature(0);temperature(10);temperature(100);}catch(char const * s) {cout<<s<<endl;}system("pause");return 0;
}//result
It reached the freezing point.
sh: 1: pause: not found

为什么答案只有It reached the freezing point

函数异常也可以抛出去由主函数来处理

void fun(int x)
{try{if(x==0)throw "异常";}catch(...){cout<<"in fun"<<endl;throw 1;}
}int main(int argec, char const *argv[])
{try{fun(0);}catch(int n){cout<<"in main"<<endl;}system("pause");return 0;
}
//输出
in fun
in main

关于C++中的一些特殊函数inline,virtual等等相关推荐

  1. 【问题解决方案】关于Python中的语句 ‘ %matplotlib inline ‘

    [问题解决方案]关于Python中的语句 ' %matplotlib inline ' 参考文章: (1)[问题解决方案]关于Python中的语句 ' %matplotlib inline ' (2) ...

  2. azure linux 配置端口,快速入门 - 在 Azure 门户中创建 Linux VM - Azure Virtual Machines | Microsoft Docs...

    您现在访问的是微软AZURE全球版技术文档网站,若需要访问由世纪互联运营的MICROSOFT AZURE中国区技术文档网站,请访问 https://docs.azure.cn. 快速入门:在 Azur ...

  3. 转载-区分C#中的Abstract函数和Virtual函数

    发现很多朋友对于C#中的Abstract和Virtual函数区分得不是很清楚,下面我通过两段代码让大家看看这两者之间到底有什么区别~~ 开发环境: VS.net 2005 使用方法: 用以下代码覆盖p ...

  4. c#中的interface abstract 与 virtual(转)

    interface用来声明接口 1.只提供一些方法规约,不提供方法主体.  如: public interface IPerson {     void getName();//不包含方法主体 } 2 ...

  5. c语言什么是内联函数,C语言中内联函数inline的使用方法

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 来源一:比特网 来源二:东方锐智 在C++中,为了解决一些频繁调用的小涵数大量消耗栈空间或者是叫栈内存的问题,特别的引入了inline修饰符,表示为内联涵 ...

  6. 求变量的数据类型,typeid,bool,C和C++的不同,new和delete,C++中的枚举,inline和可变参数模板,auto和函数模板,宽字符

    求变量的数据类型,通过函数typeid(变量名).name();获得变量的数据类型. 案例如下: #include<iostream> #include<stdlib.h> v ...

  7. 浅析C#中new、override、virtual关键字的区别

    OO思想现在已经在软件开发项目中广泛应用,其中最重要的一个特性就是继承,最近偶简单的复习了下在C#中涉及到继承这个特性时,所需要用到的关键字,其中有一些关键点,特地整理出来,方便大家查阅. 一.在C# ...

  8. c#中的interface abstract与virtual的介绍与使用

    abstract 与virtual : 方法重写时都使用 override 关键字,interface中的方法和abstract方法都要求实现. 1:interface用来声明接口 1.1.只提供一些 ...

  9. c#中的interface abstract与virtual

    abstract 与virtual : 方法重写时都使用 override 关键字,interface中的方法和abstract方法都要求实现 interface用来声明接口 1.只提供一些方法规约, ...

最新文章

  1. QT OpenCV Linux
  2. JMeter压力测试入门教程[图文]
  3. 虚拟打印机开发日志(一):使用x64 WIN7编译环境编译的完整步骤
  4. 诊断网络层和应用层交互_基于SoC的数据采集与交互系统解决方案
  5. iOS 真机调试包集合 包含 iOS 12.4 不断更新
  6. CUDA: OpenCV requires enabled ‘cudev‘ module from ‘opencv_contrib
  7. 科学计算机java算法实现,(Java)科学型计算器开发及实现.doc
  8. celery的中文_celery异步任务框架
  9. 【转】.NET试题总结二
  10. POJ-2480 Longge's problem 欧拉函数
  11. Hbase具体操作(图文并茂且超超全~~~)
  12. Could not find artifact org.olap4j:olap4j:pom:0.9.7.309-JS-3 in alimaven
  13. [原创]ASP.net 2.0 ObjectDataSource 应用操作代码实例(1)-—访问SQL2005
  14. 基于卷积神经网络与迁移学习的油茶病害图像识别
  15. react-native ios push 本地view
  16. css3静态进度条,CSS3+JS实现静态圆形进度条
  17. 美国阿肯色州闪电彩虹共享一片天空(组图)
  18. 关于tensor的shape理解
  19. [转载]Android性能优化来龙去脉总结
  20. 华为ensp防火墙web登陆配置

热门文章

  1. python飞机大战概要设计_飞机大战--毕业论文--初稿.doc
  2. 0x00007ffff3d3ecd0 in _IO_vfprintf_internal (s=0x7ffff40b5620 <_IO_2_1_stdout_>
  3. 基于.Net TcpListener 实现 WebSocketServer 通讯
  4. JZOJ 5585 老夫
  5. 【BZOJ】 2049 SDOI洞穴探险 【乱搞】
  6. java读取word中的表格并存入到mysql数据库中实例
  7. 线性表初始化运行代码
  8. linux运行欧陆风云,释放强大性能:Linux内核迎来QMEU 6.0的M68k虚拟机补丁
  9. pandas的基本功能与常用的数学统计方法
  10. 考研英语唐叔的语法课笔记