C++ 简介

        C++是一种静态类型的、编译式的、通用的、大小写敏感的、不规则的编程语言,支持过程化编程、面向对象编程和泛型编程。C++目前被认为是一种中级语言,它综合了低级语言和高级语言的特点。C++ 是由 Bjarne Stroustrup 于 1979 年在新泽西州美利山贝尔实验室开始设计开发的。C++从C语言扩充发展而来,依次经历了new C -> C with class -> C++,在1983年更名为C++。因此,任何合法的C语言程序都是合法的C++程序。但是,C++语言检查器比C语言检查要严格匹配,C++严谨了编程风格。

当然这里也给一下其他各个语言的出现时期:B语言(1969)、C语言(1972)、C++语言(1983)Java语言(1996)与C#语言(2000)

标准的 C++ 由三个重要部分组成:

  • 核心语言,提供了所有构件块,包括变量、数据类型和常量,等等。
  • C++ 标准库,提供了大量的函数,用于操作文件、字符串等。
  • 标准模板库(STL),提供了大量的方法,用于操作数据结构等。

其中向对象程序设计包含四大特性:封装、抽象、继承、多态。

C++ 支持多种编程风格。您可以使用 Fortran、C、Smalltalk 等任意一种语言的编程风格来编写代码。每种风格都能有效地保证运行时间效率和空间效率。

C++基于现有的传承性,当前主要用来编写设备驱动程序和其他要求实时性的硬件操作软件,操作系统中很多常用接口都是直接使用C++编写的。当然C++也不是不可以用来编写界面程序,基于QT架构开发比较多见。

ANSI 标准是为了确保 C++ 的便携性 —— 您所编写的代码在 Mac、UNIX、Windows、Alpha 计算机上都能通过编译。由于 ANSI 标准已稳定使用了很长的时间,所有主要的 C++ 编译器的制造商都支持 ANSI 标准。表中给出了各个C++标准发布的详细日期。

发布时间 通称 备注
2017 C++17 第五个C++标准
2017 coroutines TS 协程库扩展
2017 ranges TS 提供范围机制
2017 library fundamentals TS 标准库扩展
2016 concurrency TS 用于并发计算的扩展
2015 concepts TS 概念库,用于优化编译期信息
2015 TM TS 事务性内存操作
2015 parallelism TS 用于并行计算的扩展
2015 filesystem TS 文件系统
2014 C++14 第四个C++标准
2011 - 十进制浮点数扩展
2011 C++11 第三个C++标准
2010 - 数学函数扩展
2007 C++TR1 C++技术报告:库扩展
2006 - C++性能技术报告
2003 C++03 第二个C++标准
1998 C++98 第一个C++标准

另外,对于gcc编译工具链所支持的对应的C++标准版本如列表下。对于不同类型的微软的VS版本可以自行查找。

GCC 版本 C++常用标准
C++98/03 C++11 C++14 C++17 GNU++98 GNU++11 GNU++14 GNU++17
10.1 ~ 8.4 c++98/c++03 c++11 c++14 c++17 gnu++98/gnu++03 gnu++11 gnu++14 gnu++17
7.5 ~ 5.5 c++98/c++03 c++11 c++14 c++1z(部分支持) gnu++98/gnu++03 gnu++11 gnu++14 gnu++1z(部分支持)
4.9.4 ~ 4.8.5 c++98/c++03 c++11 c++1y(部分支持) gnu++98/gnu++03 gnu++11 gnu++1y(部分支持)
4.7.4 c++98 c++11(部分支持) gnu++98 gnu++11(部分支持)
4.6.4 c++98 c++0x(部分支持)  gnu++98 gnu++0x(部分支持)
4.5.4 c++98 c++0x(部分支持)  gnu++98 gnu++0x(部分支持)
备注:使用静态类型的编程语言是在编译时执行类型检查,而不是在执行时执行类型检查。

向对象程序最关键的地方在于必须能够表现三大特性:封装,继承,多态!
封装指的是类中的敏感数据在外界是不能访问的;继承指的是可以对已经存在的类
进行代码复用,并使得类之间存在父子关系;多态指的是相同的调用语句可以产生
不同的调用结果。因此,如果希望用 C 语言完成面向对象的程序,那么肯定的,

必须实现这三个特性;否则,最多只算得上基于对象的程序(程序中能够看到对象
的影子,但是不完全具备面向对象的 3 大特性)。

课程中通过 void* 指针保证具体的结构体成员是不能在外界被访问的,以
此模拟 C++ 中 private 和 protected。因此,在头文件中定义了如下的语句:
  typedef void Demo;
  typedef void Derived;
Demo 和 Derived 的本质依旧是 void, 所以,用 Demo* 指针和 Derived* 指针

指向具体的对象时,无法访问对象中的成员变量,这样就达到了“外界无法访问类
中私有成员”的封装效果!

  继承的本质是父类成员与子类成员的叠加,所以在用 C 语言写面向对象程
序的时候,可以直接考虑结构体成员的叠加即可。课程中的实现直接将 struct
ClassDemo d 作为 struct ClassDerived 的第一个成员,以此表现两个自定义数
据类型间的继承关系。因为 struct ClassDerived 变量的实际内存分布就是由

struct ClassDemo 的成员以及 struct ClassDerived 中新定义的成员组成的,这

样就直接实现了继承的本质,所以说 struct ClassDerived 继承自 struct
ClassDemo。

  下一步要实现的就是多态了!多态在 C++ 中的实现本质是通过虚函数表完
成的,而虚函数表是编译器自主产生和维护的数据结构。因此,接下来要解决的问
题就是如何在 C 语言中自定义虚函数表?课程中认为通过结构体变量模拟 C++
中的虚函数表是比较理想的一种选择,所以有了下面的代码:

struct VTable
{
  int (*pAdd)(void*, int);
};

  必须要注意的是,课程中由于复制粘贴的缘故,误将 pAdd 指针的类型定义成了
int (*)(Derived*, int) , 这从 C 语言的角度算不上错误,因为 Derived* 的本质就
是 void* , 所以编译运行都没有问题。但是,从面向对象的角度,这里可以说是
一种语义上的错误!因为 pAdd 必须可以指向父类中定义的 Add 函数版本,也可
以指向子类中定义的 Add 函数版本,所以说用 Derived* 作为第一个参数表示实
际对象并不合适,应该直接使用 void* 。

  有了类型后就可以定义实际的虚函数表了,在 C 语言中用具有文件作用域
的全局变量表示实际的虚函数表是最合适的,因此有了下面的代码:

// 父类对象使用的虚函数表

static struct VTable g_Demo_vtbl =
{
  Demo_Virtual_Add
};
// 子类对象使用的虚函数表
static struct VTable g_Derived_vtbl =
{
  Derived_Virtual_Add
};

  每个对象中都拥有一个指向虚函数表的指针,而所有父类对象都指向
g_Demo_vtbl,所以所有子类对象都指向 g_Derived_vtbl。当一切就绪后,实际
调用虚函数的过程就是通过虚函数表中的对应指针来完成的。

你可能感兴趣的:(C++,c++,开发语言)