在第一章致读者的末尾,作者写了这样一段话:“The question ‘‘How does one write good programs in C++?’’ is very similar to the question ‘‘How does one write good English prose?’’ There are two answers: ‘‘Know what you want to say’’ and ‘‘Practice. Imitate good writing.’’ Both appear to be as appropriate for C++ as they are for English – and as hard to follow.”

对于这一点实在是深有体会的,计算机语言与人类自然语言有其相似之处,我们观察儿童如何学习母语,就可以知道模仿->练习循环往复执行,从而不断提高语言能力是一个多么现实的过程,这个过程真真切切地发生在我们每个人的身上。然而计算机语言的学习更像外语的学习,如何高效地学习外语则需要我们去参考母语的学习,把母语学习的经验向外语学习进行迁移,这样的过程看上去复杂,实际上是最高效的。

在1.8节,作者给出了忠告,忠告的第一条中写道:

[1] When you program, you create a concrete representation of the ideas in your solution to some
problem. Let the structure of the program reflect those ideas as directly as possible:
[a] If you can think of ‘‘it’’ as a separate idea, make it a class.
[b] If you can think of ‘‘it’’ as a separate entity, make it an object of some class.
[c] If two classes have a common interface, make that interface an abstract class.
[d] If the implementations of two classes have something significant in common, make that
commonality a base class.
[e] If a class is a container of objects, make it a template.
[f] If a function implements an algorithm for a container, make it a template function implementing
the algorithm for a family of containers.
[g] If a set of classes, templates, etc., are logically related, place them in a common namespace.

这其实是个伏笔,在书中的第二章和第三章对此进行了解释,在稍后的章节中对此还进行了详细的解释。这其实也需要自学的经验进行配合,作者在原书中同样也说了“However, a thorough understanding of every detail mentioned in this chapter is not a requirement for understanding the following chapters. Consequently, you may prefer to skim through this chapter, observing the major concepts, and return later as the need for understanding of more details arises.” 对于自学者而言,书是需要读多遍的,至少读两遍,第一遍可以称为预习,第二遍称为温习或复习,孔子说温故而知新,可以为师也。可以说温故总是可以得到新知的,除非你第一遍根本就一点没懂,那就需要更多遍的阅读或学习了。

关于作者的忠告,还想再补充两句。不知道作者是否知道Alan Perlis说的这句话:“每个人都可以被教授如何雕塑;而对米开朗基罗来说,能教给他的倒是怎样能够不去雕塑。杰出的程序员也一样”。作者在忠告中的表述完全达到了Alan Perlis以上这句话的效果,换言之,这本书是为杰出程序员预备的。

基于作者指出的计算机语言学习来源于模仿和实践,对C++语言的学习将采用对书中案例进行模仿和实践的学习方法,给出程序运行的结果并加以分析。

//过程式程序设计
//page 21
// No guarantees offered.#include <iostream>
double sqrt(double arg)
{double err = 0.0000001;double low = 0.0;double high = arg;double mid = (low + high) / 2;while ((high-low)>err){if (mid*mid >arg){high = mid;}else{low = mid;}mid = (high + low)/2;}return mid;
}/*void f()
{double root2= sqrt(2);
}*/int main()
{double root2= sqrt(2);std::cout<<root2<<"\n";
}

//过程式程序设计
//page 23
//No guarantees offered.
#include <iostream>using namespace std;int main()
{int tries = 1;while (tries < 4 ){cout<<"Do you want to proceed (y or n )?\n"; // write questionchar answer = 0;cin >> answer; // read answerswitch (answer){case 'y':return true;case 'n':return false;default :cout<<"Sorry, I don't understand that.\n";tries = tries + 1;}}cout<<"I'll take that for a no.\n";return false;//cout << "Hello world!" << endl;//return 0;
}
Do you want to proceed (y or n )?
1
Sorry, I don't understand that.
Do you want to proceed (y or n )?
1
Sorry, I don't understand that.
Do you want to proceed (y or n )?
1
Sorry, I don't understand that.
I'll take that for a no.Process returned 0 (0x0)   execution time : 10.571 s
Press any key to continue.
// Simple inch<->cm conversion program illustrating basic I/O and computation.// pg 50, sec 3.6, Input// No guarantees offered. Constructive comments to bs@research.att.com#include<iostream>using namespace std;int main()
{const float factor = 2.54;    // 1 inch equals 2.54 cmfloat x, in, cm;char ch = 0;cout << "enter length: ";cin >> x;       // read a floating-point numbercin >> ch;     // read a suffixswitch (ch) {case 'i':        // inchin = x;cm = x*factor;break;case 'c':     // cmin = x/factor;cm = x;break;default:in = cm = 0;break;}cout << in << " in = " << cm << " cm\n";return 0;   // redundant in ISO C++
}
enter length: 1
l
0 in = 0 cmProcess returned 0 (0x0)   execution time : 10.191 s
Press any key to continue.
// program illustrating basic I/O.// pg 45, sec 3.6, Input// No guarantees offered.#include<iostream>using namespace std;int main()
{string str;cout<<"Please enter your name\n";cin >>str;cout<<"Hello,"<<str<<"!\n";
}
Please enter your name
H XP
Hello,H!Process returned 0 (0x0)   execution time : 26.079 s
Press any key to continue.
// program illustrating basic I/O.// pg 45, sec 3.6, Input// No guarantees offered.#include<iostream>using namespace std;int main()
{string str;cout<<"Please enter your name\n";
//    cin >>str;getline(cin,str);cout<<"Hello,"<<str<<"!\n";
}
Please enter your name
Eric Bloodaxe
Hello,Eric Bloodaxe!Process returned 0 (0x0)   execution time : 13.009 s
Press any key to continue.
// Count occurrences of character in string using find()
// to illustrate simple use of iterators and algorithms.// pp 57-58, sec 3.8.1, Use of Iterators// No guarantees offered. Constructive comments to bs@research.att.com#include<iostream>
#include<algorithm>
#include<string>using namespace std;int count(const string& s, char c)    // count occurrences of c in s
{int n = 0;string::const_iterator i = find(s.begin(),s.end(),c);while (i != s.end()) {++n;i = find(i+1,s.end(),c);}return n;
}void f()
{string m = "Mary had a little lamb";int a_count = count(m,'a');cout << "\"" << m << "\" contains " << a_count << " 'a's\n";
}int main()
{f();return 0;  // redundant in ISO C++
}
"Mary had a little lamb" contains 4 'a'sProcess returned 0 (0x0)   execution time : 0.010 s
Press any key to continue.
// Count occurrences of elements in various containers using find()
// to illustrate generic algoriths and iterators.// pp 58-59, sec 3.8.1, Use of Iterators// No guarantees offered. Constructive comments to bs@research.att.com#include<iostream>
#include<algorithm>
#include<string>
#include<complex>
#include<vector>
#include<list>using namespace std;typedef complex<double> dcomplex; // In the book, I cheated slightly, sorry
// the standard library complex is a templatetemplate<class C, class T> int count(const C& v, T val)
{typename C::const_iterator i = find(v.begin(),v.end(),val);   // "typename;" see C.13.5int n = 0;while (i != v.end()) {++n;++i;   // skip past the element we just foundi = find(i,v.end(),val);}return n;
}void f(list<dcomplex>& lc, vector<string>& vc, string s)
{int i1 = count(lc,dcomplex(1,3));int i2 = count(vc,"Chrysippus");int i3 = count(s,'x');cout << "number of complex(1,3)s " << i1 << "\n";cout << "number of \"Chrysippus\"s " << i2 << "\n";cout << "number of 'x's in \"" << s << "\" : " << i3 << "\n";
}int main()
{vector<string> philo;philo.push_back("Aristotle");philo.push_back("Plato");philo.push_back("Chrysippus");philo.push_back("Zeno");list<dcomplex> spline;spline.push_back(dcomplex(1,3));spline.push_back(dcomplex(1,7));spline.push_back(dcomplex(1,3));spline.push_back(dcomplex(7,3));string boat = "Exxon Valdez";f(spline,philo,boat);return 0;  // redundant in ISO C++
}
number of complex(1,3)s 2
number of "Chrysippus"s 1
number of 'x's in "Exxon Valdez" : 2Process returned 0 (0x0)   execution time : 0.009 s
Press any key to continue.

根据上面这个完整的程序的启发,就可以对2.5节模块化和数据抽象栈Stack进行实现了。

先给出头文件stack.h

//模块化程序设计(类和数据抽象)
//No guarantees offered.#ifndef STACK_CLASS_H_INCLUDED
#define STACK_CLASS_H_INCLUDED#endif // STACK_CLASS_H_INCLUDED
class Stack
{char* v;int top;int max_size;
public://class Underflow{};//class  Overflow{};//class  Bad_size{};Stack(int s);~Stack();void push(char c);char pop();};

接下来给出Stack的具体实现Stack.c:

//模块化程序设计(类和数据抽象)
//No guarantees offered.#include "stack class.h"
#include<iostream>
using namespace std;
Stack::Stack(int s)
{top=0;//if(s<0||10000<s) throw Bad_size();if(s<0||10000<s) cout<<"Bad size."<<endl;max_size=s;v=new char[s];
}Stack::~Stack()
{delete[] v;
}void Stack::push(char c)
{//if(top==max_size) throw Overflow();if(top==max_size) cout<<"Overflow."<<endl;v[top]=c;top=top+1;
}char Stack::pop()
{//if (top==0) throw Underflow();if (top==0) cout<<"Underflow."<<endl;top=top-1;return v[top];
}

最后给出一个简单的应用user.c

//模块化程序设计(类和数据抽象)
//No guarantees offered.#include "stack class.h"
#include<iostream>using namespace std;int main()
{Stack s_var1(10);s_var1.push('a');s_var1.push('A');cout<<s_var1.pop()<<"\n";
}

运行结果如下所示:

AProcess returned 0 (0x0)   execution time : 0.008 s
Press any key to continue.

总结以上模块化程序设计的思路:用户代码放在user.c中,在stack.c和user.c中的代码共享通过stack.h提供界面,除此之外这两个文件就是互不相关的,可以分别进行编译。

抽象类型的实现:

首先给出头文件:

#ifndef STACK_H_INCLUDED
#define STACK_H_INCLUDED#endif // STACK_H_INCLUDED
class Stack
{public:class Underflow{};class  Overflow{};virtual void push(char c)=0;virtual char pop()=0;};class Array_stack:public Stack
{char* p;int top;int max_size;
public:Array_stack(int s);~Array_stack();void push(char c);char pop();
};

给出stack具体实现:

#include"Stack.h"
#include<iostream>
using namespace std;Array_stack::Array_stack(int s)
{top=0;//if(s<0||10000<s) throw Bad_size();if(s<0||10000<s) cout<<"Bad size."<<endl;max_size=s;p=new char[s];
}Array_stack::~Array_stack()
{delete[] p;cout<<"delete complete.\n";
}void Array_stack::push(char c)
{//if(top==max_size) throw Overflow();if(top==max_size) cout<<"Overflow."<<endl;p[top]=c;top=top+1;
}char Array_stack::pop()
{//if (top==0) throw Underflow();if (top==0) cout<<"Underflow."<<endl;top=top-1;return p[top];
}

最后给出一个应用和显示结果:

#include <iostream>
#include "Stack.h"
using namespace std;int main()
{Array_stack Array1(10);Array1.push('a');Array1.push('A');cout<<Array1.pop()<<"\n";cout << "Hello world!" << endl;return 0;
}
A
Hello world!
delete complete.Process returned 0 (0x0)   execution time : 0.016 s
Press any key to continue.

这里需要指出的是程序是在运行结束时自动调用了析构函数 ~Array_stack()。

虚函数的机理,先给出一段代码:

首先是头文件

#ifndef STACK_H_INCLUDED
#define STACK_H_INCLUDED#endif // STACK_H_INCLUDED
#include<list>using namespace std;class Stack
{public:class Underflow{};class  Overflow{};virtual void push(char c)=0;virtual char pop()=0;};class Array_stack:public Stack
{char* p;int top;int max_size;
public:Array_stack(int s);~Array_stack();void push(char c);char pop();
};class List_stack:public Stack
{list<char> lc;
public:List_stack() {}void push(char c);char pop();
};

然后是被封装隐藏的stack

#include"stack.h"
#include<iostream>
#include<list>
using namespace std;Array_stack::Array_stack(int s)
{top=0;//if(s<0||10000<s) throw Bad_size();if(s<0||10000<s) cout<<"Bad size."<<endl;max_size=s;p=new char[s];
}Array_stack::~Array_stack()
{delete[] p;cout<<"delete complete.\n";
}void Array_stack::push(char c)
{//if(top==max_size) throw Overflow();if(top==max_size) cout<<"Overflow."<<endl;p[top]=c;top=top+1;
}char Array_stack::pop()
{//if (top==0) throw Underflow();if (top==0) cout<<"Underflow."<<endl;top=top-1;return p[top];
}void List_stack::push(char c)
{lc.push_front(c);
}char List_stack::pop()
{char x=lc.front();lc.pop_front();return x;
}

最后给出案例:

#include <iostream>
#include"stack.h"
using namespace std;int main()
{Array_stack as(10);List_stack  ls;as.push('a');as.push('A');ls.push('b');ls.push('B');cout<<as.pop()<<"\n";cout<<ls.pop()<<"\n";cout << "Hello world!" << endl;return 0;
}

显示的执行结果如下:

A
B
Hello world!
delete complete.Process returned 0 (0x0)   execution time : 0.010 s
Press any key to continue.

引用书中原文如下:The functions in the vtbl allow the object to be used correctly even when the size of the object and the layout of its data are unknown to the caller. All the caller needs to know is the location of the vtbl in a Stack and the index used for each virtual function. This virtual call mechanism can be made essentially as efficient as the ‘‘normal function call’’ mechanism. Its space overhead is one pointer in each object of a class with virtual functions plus one vtbl for each such class.

关于堆栈,作者就死磕到底了,堆栈是一个对于计算机硬件具体而对于实际应用抽象和一般的概念。那么实际应用中有使用字符的堆栈,也有使用整数的堆栈,如何隐藏实现细节,实现对实际应用透明而且独立的表达了。作者给出了这样的程序设计范式:

正如公文写作有模板,论文写作有模板,规范化给语言的交流提供了方便阅读的便利条件。

同样,在程序设计中也可以套用模板实现堆栈,以下给出具体的程序实现。

#ifndef STACK_H_INCLUDED
#define STACK_H_INCLUDED#endif // STACK_H_INCLUDED#include<iostream>
using namespace std;template<class T>class Stack
{T* v;int top;int max_size;
public:class Underflow{};class Overflow{};Stack(int s);~Stack();void push(T);T pop();
};template<class T>Stack<T>::Stack(int s)
{top=0;if(s<0||10000<s) cout<<"Bad size."<<endl;max_size=s;v=new T[s];
}template<class T>Stack<T>::~Stack()
{delete[] v;cout<<"delete complete.\n";
}template<class T>void Stack<T>::push(T c)
{if (top==max_size){throw Overflow();cout<<"Overflow."<<endl;}v[top]=c;top=top+1;
}template<class T>T Stack<T>::pop()
{if (top==0){throw Underflow();cout<<"Underflow."<<endl;}top=top-1;return v[top];
}

给出一个具体应用案例如下:

#include<iostream>
#include<complex>
#include"stack.h"
using namespace std;typedef complex<int> dcomplex;
int main()
{Stack<char> sc(20);Stack<dcomplex> scplx(30);sc.push('c');scplx.push(dcomplex(1,2));cout<<sc.pop()<<"\n";cout<<scplx.pop()<<"\n";}

运行结果如下所示:

c
(1,2)
delete complete.
delete complete.Process returned 0 (0x0)   execution time : 0.007 s
Press any key to continue.

这里,作者给出了一个定义,一个能保存某种类型的一集元素的类,一般被称为一个容器类,或简单地称为容器。(A class holding a collection of elements of some type is commonly called a container class, or simply a container.)

在C++程序设计语言第四版(最新版)中,增加了并发这一章节,考虑到Bjarne Stroustrup已经是70多岁的高龄,这一版有可能成为绝版。众所周知,现代的cpu处理器无论是ARM架构还是x86架构,早已经迈入了多核心时代。并发,也就是多个任务同时执行成为编程提高吞吐率(用多个处理器共同完成单个计算)和提高响应速度(允许程序的一部分在等待响应时,另一部分继续执行)。然而多任务同时执行有别于单任务,需要在程序中做一些特殊的处理,否则往往会出现意想不到的结果(非预料的运行结果)。以下给出具体的例子。

#include <iostream>
#include <thread>
using namespace std;void f()
{cout<<"Hello ";
}struct F
{void operator()(){cout<<"Parallel World!\n";}
};int main()
{thread t1 {f};thread t2 {F()};t1.join();t2.join();return 0;}

输出结果如下所示:

Hello Parallel World!Process returned 0 (0x0)   execution time : 0.006 s
Press any key to continue.

这样的运行结果是我们想要的,然而Bjarne Stroustrup却指出在这个程序中,f和F()都使用了对象cout,但没有采取任何形式的同步措施。因此输出结果将是不可预测的,而且程序每一次执行都可能得到不同结果,毕竟两个任务中的操作的执行顺序根本无法确定。程序可能会产生下面这样的“奇怪的”输出:PaHerallllel o World!

我又重新运行了几次程序,分别得到的输出结果如下:

Parallel World!
Hello
Process returned 0 (0x0)   execution time : 0.007 s
Press any key to continue.

该程序在一个单核CPU上运行,得到如下错误:

terminate called after throwing an instance of 'std::system_error'what():  Enable multithreading to use std::thread: Operation not permitted
已放弃 (核心已转储)

Bjarne Stroustrup对这个问题的解决方案是:在定义一个并发程序的任务时,我们的目标是保持任务的完全隔离,唯一的例外是任务间的通信部分;这种通信应该以一种简单明显的方式进行。考虑一个并发任务的最简单的方式是把它看作一个可以与调用者并发执行的函数。为此,我们只需要传递实参、获取结果并保证两者不会同时使用共享数据(不存在数据竞争)。

C++程序设计语言导论相关推荐

  1. c语言程序设计入门导论,程序设计入门——C语言

    spContent=C语言是古老而长青的编程语言,它具备了现代程序设计的基础要求,它的语法是很多其他编程语言的基础,在系统程序.嵌入式系统等领域依然是无可替代的编程语言,在各类编程语言排行榜上常年占据 ...

  2. 进阶 c程序设计语言,C程序设计进阶

    你将学到什么 Computer Display Standard C Programming C++ 课程概况 如果说学习过<计算导论与C语言基础>,你已经迈入了C语言的殿堂,那么< ...

  3. 201803考试批次2C 程序设计语言,201803考试批次2可视化程序设计(VB)D卷

    201803考试批次2可视化程序设计(VB)D卷 2018-12-15 903 201803考试批次2可视化程序设计(VB)D卷 可视化程序设计(VB) 一 .单项选择题 (共 10 题.0 / 20 ...

  4. 计算机浙大网java网站,网络课程—非计算机专业JAVA程序设计语言

    <非计算机专业JAVA程序设计语言> 一.主要目标和主要内容: 该课程面向全校非计算机专业理工类本科生,是程序设计语言类必修的公共基础课之一.该课程的前导课程是<大学计算机基础> ...

  5. 各代程序设计语言拓扑

    Wegner根据语言的功能和产生的时间,将一些流行的高级语言进行了分类. 第一代 (1954-1958) Fortran I Algol 58 Flowmatic IPL V 第二代 (1959-19 ...

  6. C 家族程序设计语言发展史

    目录 文章目录 目录 程序设计语言发展史 程序设计语言发展史 1950 年代末期,大量新的计算机编程语言涌现,而这些新语言大都围绕单个体系结构,如 UNIVAC 计算机.IBM700 系列计算机等进行 ...

  7. Ada 程序设计语言(The Ada Programming Language)[第二集]

    Ada 程序设计语言(The Ada Programming Language)[第二集]- -   2.5.2 通用离散类型属性 离散类型包括整型和枚举型,除了上述的属性外,还有: S'Pos   ...

  8. 计算机与程序设计语言教案,计算机程序设计(c语言)教案

    计算机程序设计(c语言)教案 (4页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 14.90 积分 计算机程序设计(C语言)教案课程名称计算机程序设计总学 ...

  9. 中国计算机学会CCF推荐国际学术会议和期刊目录-软件工程/系统软件/程序设计语言

    软件工程/系统软件/程序设计语言 中国计算机学会推荐国际学术期刊  (软件工程/系统软件/程序设计语言) 一.A类 序号 刊物简称 刊物全称 出版社 网址 1 TOPLAS ACM Transacti ...

最新文章

  1. matlab电路环流,基于MATLAB的单芯电缆金属护套环流分析研究
  2. oracle11g知乎,【AAAI】AAAI2020录用论文汇总(二)
  3. 编解码:Base64编码在URL中的应用
  4. 【PL/SQL】Excel批量往数据库中插入数据:
  5. macbook图形化编程_如何判断MacBook使用的是哪种图形芯片(并进行切换)
  6. Maven下载Sql Server 2008的驱动包
  7. LeetCode 290. 单词规律(哈希)
  8. juery的跨域请求2
  9. Bfs 逃脱(牛客网)
  10. python unpack 到数列_842. 将数组拆分成斐波那契数列(Python)
  11. vue移动端UI组件
  12. Python从入门到数据分析第一篇—Python简介- Python介绍与初探
  13. 孕育独角兽独立融资上市,互联网巨头都藏着什么“阳谋“?
  14. 用Windows电脑看epub小说,哪些阅读器软件更好用?
  15. delphi11中使用python4delphi组件
  16. 个人博客网站接入来必力评论系统
  17. 切线和倒数_原函数的导数和反函数的导数为什么是倒数关系
  18. 数据处理案例一之求同存异
  19. Linux链接命令和搜索命令
  20. revit服务器系统,Revit 2020 产品系统要求

热门文章

  1. 温度传感器温度数据LED屏幕展示--物联网服务器搭建
  2. Java中创建对象的六个步骤 细分后(new关键字)对象头详细介绍
  3. 常用的跟外链相关的几种工具
  4. IDEA 警告 the package is not inside non-bundled dependency
  5. Vue3——v-md-editor(markDown编辑器)使用教程
  6. HDU 4545-魔法串
  7. Linux C/C++ or 嵌入式面试之《C/C++笔面试系列》(1) C语言经典笔面试题(上)
  8. [网鼎杯 2020 青龙组]AreUSerialz
  9. CSUST 2007 我爱吃烧烤 题解(状压dp)
  10. Mac端Charles抓包之后unkown的具体解决方案