Chapter 1.关于类的关键字

1. class,struct与union

1.1简述:

​ class是我们最为熟悉的C++类声明的关键字,便不再多提了,而C++的struct相比C中struct而言很不一样了,已经扩充了很多东西,而union是一种一种特殊的类,相比前两者就比较少用了,但也不排除有派得上用场的时候。

1.2 详解:

struct与class

​ 刚从C转自C++时,大多数人总是仍把struct当作原来熟悉的包含各种数据的结构体,其实不然。士别三日,即更刮目相看。struct已经可以包含成员函数,可以继承,甚至可以多态,class能做到的,它基本上都可以做到。

​ 那为啥还要class呢?那是因为它们二者还是有区别的,而且关键是它们的定位是不同的。

​ 首先,struct与class最本质的区别是默认访问控制----struct是public的,class是private的。struct可以继承class,同样class也可以继承struct,但是public继承还是private继承取决于子类而不是基类

​ 简单来说,struct作为数据结构的实现体,它默认的数据访问控制是public的,而class作为对象的实现体,它默认的成员变量访问控制是private的。

​ 其次,“class”这个关键字还用于定义模板参数,就像“typename”。但关键字“struct”不用于定义模板参数。这一点在Stanley B.Lippman写的Inside the C++ Object Model有过说明。

​ 最后,struct仍包含在C中的简单{}赋初值操作,但是这样简单的copy操作,只能发生在简单的数据结构上,而不应该放在对象上。加入一个构造函数或是一个虚函数会使struct更体现出一种对象的特性,而使此{}操作不再有效。事实上,是因为加入这样的函数,使得类的内部结构发生了变化。而加入一个普通的成员函数呢?你会发现{}依旧可用。其实你可以将普通的函数理解成对数据结构的一种算法,这并不打破它数据结构的特性。

​ 总而言之,struct更适合看成是一个数据结构的实现体,class更适合看成是一个对象的实现体

​ 详细代码及学习自:https://www.cnblogs.com/starfire86/p/5367740.html

union与struct

​ C++ union结构式一种特殊的类。它能够包含访问权限、成员变量、成员函数(可以包含构造函数和析构函数)。它不能包含虚函数和静态数据变量。它也不能被用作其他类的基类,它本身也不能有从某个基类派生而来。union中得默认访问权限是public。

​ union类型是共享内存的,以size最大的结构作为自己的大小。每个数据成员在内存中得其实地址是相同的。

​ 即当union的第二个数据成员在赋初值时,会覆盖第一个数据成员的值,存储在同一个地址上。但正因为这个特性,我们可以用它来判断CPU是大端模式还是小端模式,具体实现见下方网址。

​ union与struct不同就在于,struct是以所有数据成员大小总和作为自己的大小,所有数据成员存储在相邻地址上。

​ 详细代码及学习自:https://blog.csdn.net/xiajun07061225/article/details/7295355


2.private,public与protected

2.1 简述

​ 一个类可以派生自多个类,这意味着,它可以从多个基类继承数据和函数。定义一个派生类,我们使用一个类派生列表来指定基类。类派生列表以一个或多个基类命名,形式如下:

	class derived-class: access-specifier base-class

​ 其中,访问修饰符 access-specifier 是 public、protectedprivate 其中的一个,base-class 是之前定义过的某个类的名称。如果未使用访问修饰符 access-specifier,则默认为 private。

​ 这三个关键字有两种情况,一种是在类内部使用,表示访问权限;另外一种是在类的继承层次中访问时,表示继承方式。

2.2 详解

​ 根据访问权限总结出不同的访问类型,如下所示:

访问 public protected private
同一个类 yes yes yes
派生类 yes yes no
外部的类 yes no no
友元类 yes yes yes

​ 一个派生类继承了所有的基类方法,但下列情况除外:

  • 基类的构造函数、析构函数和拷贝构造函数。

  • 基类的重载运算符。

  • 基类的友元函数。

​ 类的成员函数可以调用类中各个属性的成员。而类的对象只能访问类的public属性成员,而不能访问private和protected属性成员。所以,类的对象访问类中private和protected的时候要借助public成员函数,这就是类的接口函数。这种访问机制实现了类的封装。

派生类类成员访问级别设置的原则:

1、需要被外界访问的成员直接设置为public

2、只能在当前类中或友元类访问的成员设置为private

3、只能在当前类,子类,友元中访问的成员设置为protected,protected成员的访问权限介于public和private之间。


3.friend

3.1 简述

​ 私有成员只能在类的成员函数内部访问,如果想在别处访问对象的私有成员,只能通过类提供的接口(成员函数)间接地进行。这固然能够带来数据隐藏的好处,利于将来程序的扩充,但也会增加程序书写的麻烦,而友元便是因此产生(ps:原来是为了程序员偷懒)。

​ 友元分为友元类和友元函数。

3.2 详解

3.2.1友元函数

​ 在定义一个类的时候,可以把一些函数(包括全局函数和其他类的成员函数)声明为“友元”,这样那些函数就成为该类的友元函数,在友元函数内部就可以访问该类对象的私有成员了。常用于共享数据或运算符重载。

将全局函数声明为友元的写法如下:

friend  返回值类型  函数名(参数表);

将其他类的成员函数声明为友元的写法如下:

friend  返回值类型  其他类的类名::成员函数名(参数表);

但是,不能把其他类的私有成员函数声明为友元。

友元函数实现代码与普通函数相同(可以在类外或类中,不用加friend和类::)

​ 友元函数虽然能使其他类的成员函数直接访问该类的私有变量,提高效率,但同时它也破坏了封装机制,所以尽量不使用成员函数,除非不得已的情况下才使用友元函数。

友元函数的参数:

因为友元函数没有this指针,则参数要有三种情况:

1、 要访问非static成员时,需要对象做参数;--常用(友元函数常含有参数)

2、 要访问static成员或全局变量时,则不需要对象做参数

3、 如果做参数的对象是全局对象,则不需要对象做参数

3.2.2友元类

​ 一个类 A 可以将另一个类 B 声明为自己的友元,类 B 的所有成员函数就都可以访问类 A 对象的私有成员。在类定义中声明友元类的写法如下:

	friend  class  类名;

​ Note:

​ (1) 友元关系不能被继承。

​ (2) 友元关系是单向的,不具有交换性。若类B是类A的友元,类A不一定是类B的友元。

​ (3) 友元关系不具有传递性。若类B是类A的友元,类C是B的友元,类C不一定是类A的友元。

详细代码及学习自:https://blog.csdn.net/insistgogo/article/details/6608672


4.virtual


5.const


6.inline

6.1 简述

​ inline 说明符,在用于函数的声明说明符序列时,将函数声明为一个 内联(inline)函数,引入inline的主要原因是用它替代C中复杂易错不易维护的宏函数。

​ 完全在class/struct/union 的定义之内定义的函数,无论它是成员函数还是非成员 friend 函数,均为隐式的内联函数。

6.2详解

​ 编译器在编译阶段完成对inline函数的处理,即对inline函数的调用替换为函数的本体。函数定义时,在返回类型前加上关键字inline即把函数指定为内联,函数申明时可加也可不加。

​ inline函数相对宏函数有如下优点:

(1)内联函数同宏函数一样将在被调用处进行代码展开,省去了参数压栈、栈帧开辟与回收,结果返回等,从而提高程序运行速度。

(2)内联函数相比宏函数来说,在代码展开时,会做安全检查或自动类型转换(同普通函数),而宏定义则不会。

(3)在类中声明同时定义的成员函数,自动转化为内联函数,因此内联函数可以访问类的成员变量,宏定义则不能。

(4)内联函数在运行时可调试,而宏定义不可以。

​ 使用inline函数,也要三思慎重。inline函数的缺点总结如下:

(1)代码膨胀。

​ inline函数带来的运行效率是典型的以空间换时间的做法。内联是以代码膨胀(复制)为代价,消除函数调用带来的开销。如果执行函数体内代码的时间,相比于函数调用的开销较大,那么效率的收获会很少。另一方面,每一处内联函数的调用都要复制代码,将使程序的总代码量增大,消耗更多的内存空间。

(2)inline函数无法随着函数库升级而升级。

如果f是函数库中的一个inline函数,使用它的用户会将f函数实体编译到他们的程序中。一旦函数库实现者改变f,所有用到f的程序都必须重新编译。如果f是non-inline的,用户程序只需重新连接即可。如果函数库采用的是动态连接,那这一升级的f函数可以不知不觉的被程序使用。

(3)是否内联,程序员不可控。

​ inline函数只是对编译器的建议,是否对函数内联,决定权在于编译器。编译器认为调用某函数的开销相对该函数本身的开销而言微不足道或者不足以为之承担代码膨胀的后果则没必要内联该函数,若函数出现递归,有些编译器则不支持将其内联。

6.3 inline函数的注意事项

​ 1)使用函数指针调用内联函数将会导致内联失败。

​ 2)如果函数体代码过长或者有多重循环语句,if或witch分支语句或递归时,不宜用内联。

​ 3)类的constructors、destructors和虚函数往往不是inline函数的最佳选择。

​ 4)一个inline函数会在多个源文件中被用到,那么必须把它定义在头文件中。

​ 可以将内联理解为C++中对于函数专有的宏,对于C的函数宏的一种改进。对于常量宏,C++提供const替代;而对于函数宏,C++提供的方案则是inline。C++的内联机制,既具备宏代码的效率,又增加了安全性,还可以自由操作类的数据成员,算是一个比较完美的解决方案。

​ 一般来说,内联机制用于优化规模较小,流程直接,频繁调用的函数。

详细代码及学习自:https://blog.csdn.net/K346K346/article/details/52065524


7.template


8.delete与default

8.1简述

​ C++11中,将具有合成版本的成员函数(即默认构造函数或拷贝控制成员)定义为 =default 来显式地要求编译器生成合成的版本(即编译器创建的默认xx函数)。

​ 可以通过将拷贝构造函数和拷贝赋值运算符定义为删除的函数来阻止拷贝,即在函数的参数列表后面加上=delete来指出我们希望将它定义为删除的。

8.2 详解

​ 二者不同之处有下:

​ 1.=default当用于类内修饰成员的声明,合成的函数将隐式地声明为内联地;当用于类外定义时,其合成的函数是非内联的。=delete只能用于函数第一次声明的时候,这与声明含义在逻辑上吻合,因为=default直到编译器生成代码时才需要,而编译器需要知道一个函数是删除的以便禁止试图使用它的操作。

​ 2.可以对任何函数指定=delete,但只能对编译器可以合成的默认构造函数或拷贝控制成员使用=default。

​ Note:析构函数不能是删除的成员,否则我们不能销毁该对象及其成员!

​ 关于合成默认构造函数 https://www.cnblogs.com/QG-whz/p/4676481.html


9.final与override


10.explicit

10.1 简述

​ explicit(显式的)的作用是“禁止单参数构造函数”被用于自动型别转换,其中比较典型的例子就是容器类型。在这种类型的构造函数中你可以将初始长度作为参数传递给构造函数。

10.2 详解

​ 首先, C++中的explicit关键字只能用于修饰只有一个参数的类构造函数, 它的作用是表明该构造函数是显示的, 而非隐式的, 跟它相对应的另一个关键字是implicit, 意思是隐藏的,类构造函数默认情况下即声明为implicit(隐式).

​ 不过,也有一个例外,当除了第一个参数以外的其他参数都有默认值的时候, explicit关键字依然有效, 此时, 当调用构造函数时只传入一个参数, 等效于只有一个参数的类构造函数。

​ 总而言之,explicit用来禁止编译器隐式调用该构造函数,以防止隐式的类型转换而造成不必要的错误,但对显式调用该函数则没有问题。

详细代码及学习自:https://www.cnblogs.com/ymy124/p/3632634.html


11.extern与static


12.constexpr

12.1 简述

​ constexpr函数是指能用于常量表达式的函数。

12.2 详解

​ constexpr函数必须遵守几项约定:函数的返回类型及所有形参的类型都得是字面值类型,而且函数体中必须有且只有一条return语句:

	constexpr int  first(){return 42};
constexptr int second=first(); //正确,second是一个常量表达式

​ 编译器在编译时验证first函数是常量表达式,将对其调用替换成结果值42.

​ 为了在编译过程中随时展开,constexpr函数被隐式地指定为内联函数。

​ Note:constexpr函数不一定返回常量表达式,若用一个非常量表达式调用它,则返回非常量表达式。

12.3 inline函数和constexpr函数

​ 和其他函数不同,内联函数和constexpr函数可在程序中多次定义,但内联函数或constexpr函数的多个定义必须完全一致,因此二者通常定义在头文件中。


​ 本文参考,并部分摘抄了上述所推荐的所有博客(毕竟在我看来写的非常好,所以强烈建议前往学习),C++p(C++经典书籍)以及cppreference.com,表示感谢知识传授,本人C++知识还有所欠缺,所以以上难免存在错误,仅供参考学习,如果大家发现错误和需要改进的地方,请大家留言给予宝贵的建议。

​ 建议如果想了解最新C++特性的,前往上面的网址进行查询。

转载标明出处:作者AMzz 博客: https://www.cnblogs.com/AMzz/

C++总结(1)keywords to the class的更多相关文章

  1. 【HDU2222】Keywords Search AC自动机

    [HDU2222]Keywords Search Problem Description In the modern time, Search engine came into the life of ...

  2. 16个基本颜色关键字 Basic color keywords

    16个基本颜色关键字 Basic color keywords Color Color Name HEX RGB   black #000000 0,0,0   silver #C0C0C0 192, ...

  3. asp.net动态设置标题title 关键字keywords 描述descrtptions

    推荐的简单做法如下: protected void Page_Load(object sender, EventArgs e){//Page titlePage.Title = "This ...

  4. hdu2222 Keywords Search ac自动机

    地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=2222 题目: Keywords Search Time Limit: 2000/1000 MS ...

  5. HDU2222 Keywords Search

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...

  6. 织梦5.7 TAG、标题、栏目以及keywords长度字符数限制修改

    织梦5.7 TAG.标题.栏目以及keywords长度字符数限制修改[图文]   标签: 织梦关键词长度修改 织梦tag长度修改 织梦标题长度修改 织梦栏目长度限制修改 织梦修改 分类: 技术操作   ...

  7. HDU 2222 Keywords Search(AC自动机模版题)

    Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others ...

  8. HDOJ2222 Keywords Search-AC自动机

    Problem Description In the modern time, Search engine came into the life of everybody like Google, B ...

  9. 页面头部title、description、keywords标签的优化

    页面头部优化<Head></Head>中间的区域中间的区域,我们称为网页的头部.在网页的头部中,通常存放一些介绍页面内容的信息,例如页面标题.描述及关键字等等.在头部优化中,除 ...

  10. AC自动机---Keywords Search

    题目网址:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=110773#problem/A Description In the moder ...

随机推荐

  1. Flask中的数据连接池

    pymsql链接数据库 import pymysql conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd=' ...

  2. powershell(一)

    Windows powershell是一种命令行外壳程序和脚本环境,它内置在win7以上版本的操作系统中,使命令行用户和脚本编写者可以利用.NET Framework的强大功能.powershell程 ...

  3. swap()函数的几种写法及优劣

    试用几种方法实现swap函数,比较效率高低. 首先说结果,最快的是赋值交换. 原因分析 gcc开启O2优化后,三个函数的汇编代码一样.是的,除了第一行的文件名,一模一样. 附代码 void swap1 ...

  4. 数据结构5_java---二叉树,树的建立,树的先序、中序、后序遍历(递归和非递归算法),层次遍历(广度优先遍历),深度优先遍历,树的深度(递归算法)

    1.二叉树的建立 首先,定义数组存储树的data,然后使用list集合将所有的二叉树结点都包含进去,最后给每个父亲结点赋予左右孩子. 需要注意的是:最后一个父亲结点需要单独处理 public stat ...

  5. Linux面试题-8

    1.Linux文件系统的文件都按其作用分门别类地放在相关的目录中,对于磁盘这种外部设备文件,一般应将其放在(C)目录中. A./bin B./etc C./dev D./lib 2.当使用mount进 ...

  6. Unity - HasExitTime用法

    本文详细分析了AnimatorController中动画切换过渡问题,即Translation过渡及hasExitTime的问题.方法为对实际项目中的所有情况进行分类,规划逻辑图,可视化分析解决这些问 ...

  7. git生成SSH秘钥

    1.进入git bash , 输入 cd ~/.ssh/ ,没有的话,自己创建 mkdir ~/.ssh , 然后进入该文件夹完成生成秘钥步骤 2.配置全局的name和email,这里是的你githu ...

  8. Python 常见异常类型

    python标准异常 异常名称                                   描述 BaseException                         所有异常的基类Sy ...

  9. unity message

    再用unity进行开发过程中,不可避免的用到消息的传递问题,以下介绍几种消息传递的方法: (一)拖动赋值 此方法即为最普通的方法,即把需要引用的游戏物体或者需要引用的组件拖动到相关公有变量的槽上,然后 ...

  10. 【阿里云IoT+YF3300】8.物联网设备用户脚本开发

    除了我们必须熟悉的网页脚本,比如JavaScript.其实在工业自动化中,组态软件是必备脚本的,只是有的脚本语言风格类似C或类似Basic而已.比如昆仑通泰的组态屏中的组态软件.通过安装组态软件可以简 ...