零基础想学习C++,应该怎么开始入手?

C++融合了3种不同的编程方式:C语言代表的过程性语言、C++在C语言基础上添加的类代表的面向对象语言、C++模板支持的泛型编程。本章将简要介绍这些传统。不过首先,我们来看看这种传统对于学习C++来说意味着什么。使用C++的原因之一是为了利用其面向对象的特性。要利用这种特性,必须对标准C语言知识有较深入的了解,因为它提供了基本类型、运算符、控制结构和语法规则。所以,如果已经对C有所了解,便可以学习C++了,但这并不仅仅是学习更多的关键字和结构,从C过渡到C++的学习量就像从头学习C语言一样大。另外,如果先掌握了C语言,则在过渡到C++时,必须摒弃一些编程习惯。如果不了解C语言,则学习C++时需要掌握C语言的知识、OOP知识以及泛型编程知识,但无需摒弃任何编程习惯。如果您认为学习C++可能需要扩展思维,这就对了。

C++程序的组成部分

零基础想学习C++,应该怎么开始入手?_第1张图片

在原始状态下,C++程序不过只是存储在某种文件中的一段在字符序列而已,但这种文件的命名通常会以.cc、.c、.cp或.cpp结尾(比如http://first.cc、first.C或first.cpp),以此来表示该文件是一段C++程序。而某些编程环境往往需要或假定用户遵循这套文件命名约定,所以当我们为将某个算法转换成与之等效的C++编程语言创建相关文件时,也务必要使用这种约定的扩展名来命名文件。

而对于文件中所包含的文本,我们接下来也要引入某种C++程序的通用格式,这种通用格式是用来描述语法(语言使用规范)的,它也需要有符合编程语言结构的写法。和本书中其他所有地方一样,这种通用格式也将遵守以下约定。

1.以等宽字体印刷的元素可被原样使用。这其中既包括int maincoutcin这些关键字,也包括<<>>这样的符号。

2.以斜体印刷的这部分通用格式将必须由程序员来负责提供具体内容,比如expression表示程序员必须在该处提供一个有效的表达式。

3.以斜体印刷的实体项代表它在别的地方已被定义。

通用格式2.1:标准C++程序

// A comment
#include-directives
using namespace std;
int main() {
    statements
   return 0;
}

在上述通用格式中,以加粗字体显示的部分只需照原样编写即可。而statements所在的部分表示的是一个不同语句组成的集合。语句是程序所能执行的最小独立操作单元。事实上到目前为止,本章已经介绍到几条语句了。这里需要说明的是,虽然在C++标准中不是必需的,但本书的C++程序都会以“return 0;”结尾。另外,main函数的主体部分将会用一对花括号{ }框住,每个函数都有这样一个将其中所有代码视为一个整体的结构。

在进入更细节的讨论之前,我们先来看一段语法正确的标准C++程序。请以程序的形式运行一下这段代码,它必须要有一个名为main的函数。(提示:下面的std是standard的缩写。)

// This program prompts for a name and prints a friendly message
#include    // for cout, cin, and endl
#include      // for the string type

using namespace std;  // Allow programmers to write cin and cout
                      // rather than std::cin and std::cout
int main() {
  string name;
  cout << "What is your name: ";
  cin >> name;

  cout << "Hello " << name;
  cout << ", I hope you're feeling well." << endl;

  return 0;
}

程序会话

What is your name: Casey
Hello Casey, I hope you’re feeling well.

这段源代码将会被输入到编译器中,由编译器将这些源代码转换成机器码。在此过程中,编译器有可能会产生报错或警告信息。这些错误是编译器在扫描该程序的源代码以及该程序所有#include文件中的附加源代码时被检测到的。例如,在上述程序中,我们在int main()之前引入了一个名为iostream的文件,因此该文件中的源代码也成为这个程序的一部分。在这里,#include指令的作用就是用被#include文件的内容替换掉该指令所在的文本。

每个C++程序通常都会用到一两个由其他程序员所提供的源码文件。事实上,C++编译器本身就提供了大量的源码文件。下面,我们就来看看将其他文件中的源码加入到自己程序中的通用格式:

通用格式2.2:#include指令

#include 
          或
#include "include-file"

在这里,#include和尖括号< >或双引号" "的部分都只需照原样编写即可,只有include-file必须是已经存在了的文件名。例如,我们在程序中加入以下#include指令,为的就是让其提供cout、cin和endl这3个对象:

#include 

但是,这个#include指令实际上为我们提供的是std::cout、std::cin和std::endl。C++标准库(iostream只是它的一部分)是定义一个叫作std的名字空间的,为了避免频繁重复写std::,我们通常会在#include 以及其他#include指令后面加上下面这行代码:

using namespace std; // Can now write cout instead of std::cout

另外请注意,在< >或" "之间不能有任何空格。

#include        // ERROR, space at end
#include " BankAccount.h"  // ERROR, space up front

通常,用尖括号< >所#include的文件应该必然属于系统的一部分,我们的系统应该可以自动找到这些文件。而被双引号" "所#include的文件则往往需要被存储到包含它们的程序所在的相同目录中。

1 标记:一个程序的最小零件

在继续介绍对象初始化和语句的通用格式之前,我们希望先带读者来了解一下编程语言中那些用于构建起更大型结构的最小零件。这将有助于我们:

  • 更容易在编码时写出语法正确的语句。
  • 更好地了解应该如何修复被编译器检出的那些错误。
  • 看懂通用格式。

C++编译器读取源代码的过程,实际上就是它在逐一识别其中各种标记(token)的过程。标记是一个程序中最小的可识别组件,我们可以将其分成以下4类:

标记分类 具体示例
特殊符号 ; ( ) << >>
关键字 return double int
标识符 main test2 firstName
字面常量 "Hello" 507 -2.1 true 'c' nullptr

2 特殊符号

特殊符号通常是一个由一到两个字符组成的序列,它往往代表着某一种特殊含义(有些也具有多重含义)。其中,有像“{”“;”“,”这样用来分割其他语言标记的特殊符号,也有像“+”“-”“<<”这种属于表达式操作符的。下面列出的是C++程序中一些被使用得比较频繁的单字符和双字符的特殊符号:

( )  .  +  -  /  *  =<  >=  //  {  }  ==  ;  <<  >>

3 标识符

标识符是我们给程序中各种事物赋予的名称,这些名称都要符合以下创建C++标识符的管理规则:

  • 标识符只能以小写字母a到z、大写字母A到Z、美元符号$以及下划线_开头。
  • 首字符之后可跟任意数量的大小写字母、数字(0到9)和下划线。
  • 标识符区分大小写,例如Ident、ident和iDENT将被认为是3个不同的标识符。

有效标识符

main cin incomeTax i MAX_SIZE
Maine cout employeeName x all_4_one
miSpelte string A1 n $motion$

无效标识符

1A 不能以数字开头
miles/Hour /是不可用字符
first Name 不能用空白符
pre-shrunk -代表的是减法操作符

C++有一个庞大的标准库,它们必然会占用掉一部分标识符。例如,名为cin的对象是用来获取用户键盘输入的,cout也是一个标准库标识符,它是终端输出对象的名称。下面所列出的这几个都是C++标准库所占用的标识符。(提示:下面的第一个标识符读作“end-ell”,作用是换行。)

endl  sqrt  fabs  pow  string  vector  width  precision  queue

程序员定义的标识符指的是创建该程序的程序员为后续的其他调用者和维护人员提供的标识符。例如,test1、finalExam、courseGrade这些是程序员定义的,也就是我们为自己所创建的标识符,所以请务必要用有明确含义的名称来表示它们的用途。

C++语言是严格区分大小写的,大写字母与小写字母代表的是不同的事物,“A”不等同于“a”。例如,每个完整的C++程序中都必须要包含main这个标识符,但MAIN或Main则不必。另外需要注意的是,程序员们在大小写的用法上会存在着一些约定俗成,有些程序员通常会尽量避免使用大写字母,有些程序员喜欢用大写来表示一些新的词汇。在本书中,我们将采用的是“camelBack”这种风格的写法,即将第一个单词之后每个单词的首字母设成大写。例如,我们将使用的是letterGrade,而不是lettergrade、LetterGrade或者letter_grade。对此,不同的程序员会有不同的风格。

4 关键字

关键字是一些具有特定用途的标识符,它们是语言标准所定义的保留字,比如像int和double这些都属于关键字。

C++关键字

break do for operator switch
case double if return typedef
char else int sizeof void
class float long struct while

C++区分大小写的特性也同样适用于关键字。例如double(这是关键字)与Double(这不是关键字)是不同的,C++的关键字始终为小写。

5 注释

注释是程序中用于注解的一部分文本,我们对注释通常有以下预期(可能是其中任意一种,也可能是全部):

  • 用于充当内部文档,辅助程序员读懂其他程序员所写的程序。当然,前提是这些注释确实澄清了程序中存在的歧义。
  • 用于解释某段代码或某个对象的具体用途。
  • 用于著名程序员的姓名和开发该程序的目的。
  • 用于描述该程序中涉及的各种元素和其他要考虑的因素。

注释可以被添加在程序中的任何地方,可以是所有C++语句的右侧,也可以自行单独一行或若干行,它们通常先以/*这两个特殊字符开头,最后以*/收尾。

/*
  A comment may
  extend over
  several lines
*/

除此之外,注释的另一种形式是在相关的文本之前加上//,这种注释同样既可以是自行单独一行,也可以被附加在某一行的后面:

// A complete C++ program
int main() {
  return 0; // This program returns 0 to the operating system
}

在本书所涉及的这些程序中,我们对单行注释通常会采用// Comment而不是/* Comment */。原因是/*之后一直到*/之前的所有代码都会被视为一段注释,只要我们不慎忘记了在注释结尾加上一个*/,就会意外地让一大段代码变成注释。而单行注释就很难造成这种大段代码变成注释的情况。

这里需要提醒的是,我们添加注释的目的是为了澄清和记录源代码的用途,以便让程序更容易被理解、更容易被调试(纠正错误)以及更易于维护(并在必要时做一些修改)。很多时候,程序员们需要依靠这些注释来理解一些几天前、几周前、几个月前、几年前乃至于几十年前写的程序。

6 C++字面常量

C++编译器可以自行识别字符串类型、整数类型、布尔类型(true/false)和浮点类型的字面常量。其中,字符串类型常量是由双引号括起来的0个或多个字符,并且所有字符都必须在同一行以内。

"Double quotes are used to delimit string constants."
"Hello, World!"

除此之外,整数类型常量是不带小数点的数字,浮点数类型常量是用小数点或科学计数法书写的常量(例如5e3 = 5 * 103 = 5000.0和1.23e-4 = 1.23 * 10-4 =0.000123),布尔类型常量即true和false。下面这些C++类型及其相应的常量示例是我们在本书会经常用到的常量对象。

类型 常量示例
int 0   1  999  -999  -2147483647  2147483647
char 'a'  '#'  '9'   '\t'(制表符)  '\n'(换行符)
double 1.23  0.5  .5  5.  2.3456e9  1e-12
bool true  false
string "Double quoted"  "Kim's"   "\n" ""(空字符串)
// Print a few C++ literals
#include   // For cout and endl
using namespace std;

int main() {
  cout << 123 << endl;
  cout << 'a' << '\t' << 'm' << endl;
  cout << 1.23 << endl;
  // true prints as 1 and false as 0
  cout << true << " and " << false << endl;
  cout << "Hello \n world" << endl;

  return 0;
}

程序输出

123
a m
1.23
1 and 0
Hello
 world

学C++从《C++ Primer Plus 第6版 中文版》开始入手

C++ Primer Plus 第6版 中文版

零基础想学习C++,应该怎么开始入手?_第2张图片

本书在介绍C++特性的同时,还讨论了基本C语言,使两者成为有机的整体。书中介绍了C++的基本概念,并通过短小精悍的程序来阐明,这些程序都很容易复制和试验。书中还介绍了输入和输出,如何让程序执行重复性任务,如何让程序做出选择,处理数据的多种方式,以及如何使用函数等内容。另外,本书还讲述了C++在C语言的基础上新增的很多特性,包括:本书在介绍C++特性的同时,还讨论了基本C语言,使两者成为有机的整体。书中介绍了C++的基本概念,并通过短小精悍的程序来阐明,这些程序都很容易复制和试验。书中还介绍了输入和输出,如何让程序执行重复性任务,如何让程序做出选择,处理数据的多种方式,以及如何使用函数等内容。另外,本书还讲述了C++在C语言的基础上新增的很多特性,包括:

  • 类和对象;
  • 继承;
  • 多态、虚函数和RTTI(运行阶段类型识别);
  • 函数重载;
  • 引用变量;
  • 泛型(独立于类型的)编程,这种技术是由模板和标准模板库(STL)提供的;

 处理错误条件的异常机制;

  • 管理函数、类和变量名的名称空间。

初级教程方法

大约20年前,C Primer Plus开创了优良的初级教程传统,本书建立在这样的基础之上,吸收了其中很多成功的理念。

  • 初级教程应当是友好的、便于使用的指南。
  • 初级教程不要求您已经熟悉相关的编程概念。
  • 初级教程强调的是动手学习,通过简短、容易输入的示例阐述一两个概念。
  • 初级教程用示意图来解释概念。
  • 初级教程提供问题和练习来检验您对知识的理解,从而适于自学或课堂教学。

基于上述理念,本书帮助您理解这种用途广泛的语言,并学习如何使用它。

  • 对何时使用某些特性,例如何时使用公共继承来建立is-a关系,提供了概念方面的指导。
  • 阐释了常用的C++编程理念和技术。
  • 提供了大量的附注,如提示、警告、注意等。

本书的作者和编辑尽最大的努力使本书简单、明了、生动有趣。我们的目标是,您阅读本书后,能够编写出可靠、高效的程序,并且觉得这是一种享受。

进阶推荐

C++语言的设计和演化

零基础想学习C++,应该怎么开始入手?_第3张图片

本书是C++的设计者Bjarne Stroustrup关于C++ 语言的最主要著作之一(另一本是《C++程序设计语言》)。在这本书中,作者全面论述了C++ 的历史和发展,C++中各种重要机制的本质、意义和设计背景,这些机制的基本用途和使用方法,讨论了C++ 所适合的应用领域和未来发展前景。本书在帮助人们深入理解C++ 语言方面的地位无可替代,值得每个关心、学习和使用C++ 语言的专业工作者、科研人员、教师和学生阅读。在这本书中,作者还从实践的角度出发,讨论了许多与程序设计语言、系统程序设计、面向对象的技术和方法、软件系统的设计和实现技术等有关的问题,值得每一个关心这些领域及相关问题的计算机工作者和学生们阅读参考。

现代C++语言核心特性解析

零基础想学习C++,应该怎么开始入手?_第4张图片

本书是一本C++进阶图书,全书分为42章,深入探讨了从C++11到C++20引入的核心特性。书中不仅通过大量的实例代码讲解特性的概念和语法,还从编译器的角度分析特性的实现原理,书中还穿插了C++标准委员会制定特性标准时的一些小故事,帮助读者知其然也知其所以然。

本书适合因为工作需要学习C++新特性的C++从业者,同样也适合对C++新特性非常感兴趣的C++爱好者。而对于C++初学者来说,也有必要在理解C++基础知识后,通过本书来领略C++的另外一道风景。

你可能感兴趣的