在学习c++中,最重要的是集中关注概念,不要迷失在语言的技术细节上。
对程序设计和设计技术的理解远比细节的理解更重要,而这种理解的根本是时间和实践。
c++支持一种逐步推进的学习方法
c++表达能力更强,为了增强这样能力,必须更多关注对象类型
c++特别强度程序结构,c++的设计就是为了使得较大的程序能够以一种更合理的方法构造出来
在大多数应用中,都存在这些片段,对大部分代码而言,它在性能上的可接受性至关重要。
当然,最大部分的代码并不在这些片段中,
对于大部分代码而言,可管理,易扩充,易测试是最关键的问题
c++比c更好的方式:
[1] 不需要宏定义,而用const定义明显的常量
而用inline避免函数调用的额外开销,
用template刻画一族函数或者类型
用namespace去避免名字冲突
[2]不要在你需要变量前去声明它,保证你能够立即初始化它,
[3]不要用malloc,new运算符能够将同样的事情做得更好。
对于realloc(),试一试vector()
[4]试着避免void*,指针算术,联合和强制,除了在某些函数和类实现的深层之外,
[5]尽量少用数组和c风格的字符串,而是用c++标准库的string和vector
有关在c++里编程的思考:
1 取得对问题的一个清晰的理解(分析)
2 标示出在一个解决方案中所涉及的关键性的概念(设计)
3 最后,在一个程序中佢描述他们(编程)
威力最大的就是一种管理复杂性的智力工具就是某种层次性的序关系,
将相互有关的概念组织到一个树形结构中,使得最一般的概念成为树的根
c++里面,派生类就是这种结构。
一个程序常常能组织成为一组类,或者一组类的有向无环图。
忠告:
2.3 过程式程序设计:
确定你需要的那些过程,
采用你能找到的“最好”算法。
2.4 模块化程序设计:
确定你需要哪种模块,
将程序分为一些模块,使得数据隐藏于模块中
c++提供一种机制,可以把相关的数据,函数等组织到一个独立的名字空间里,
例如模块Stack的用户界面可以按如下的方式声明和使用:
namespace Stack{
void push(char);
char pop();
}
void f()
{
Stack::push(‘c’);
if(Stack::pop()!=’c’) error(“impossible”)
}
这里的Stack::限定词表明push()和pop()是来自Stack名字空间,这些名字的使用将不会与之干扰,不会引起混乱。
Stack的定义可以通过程序的另一个单独编译部分提供:
namespace Stack{
const int max_size=200;
char v[max_size];
int top =0;
void push(char c ); {/*检查上溢并压入c*/}
char pop();{/*检查下溢并且弹出*/}
}
2.4.1分别编译:
2.4.2异常处理:
当一个程序被设计为一集模块以后,对于错误的处理也必须在这些模块的基础上考虑
2.5数据抽象
2.5.1定义类型模块
基于模块的程序设计趋于以一个类型的所有数据为中心,在某个类型管理模块的控制之下工作,例如,我们希望有很多堆栈,而不像前面那样只用一个由Stack模块提供的堆栈,我们就可能会定义一个堆栈管理器,具有如下界面:
namespace Stack{
struct Rep;//在另外某个地方定义堆栈布局,
typedef Rep &stack;//确定stack是对Rep的引用。这里的 想法是堆栈是由Stack::stack的表示
stack create(); //创建一个新的堆栈
void destroy(stack s,char c);//删除s
void push(stack s,char c);//将c压入s
char pop (stack s);// 弹出s
}
堆栈由Stack::stack表示,进一步细节对用户隐藏
一个Stack::stack用起来很像一个内部类型的变量:
struct Bad_pop
{
};//深表怀疑
void f()
{
Stack::stack s1= Stack::create();
Stack::stack s2= Stack::create();
Stack::push(s1,’c’);
Stack::push(s2,’k’);
if {Stack::pop(s1)!=’c’) throw Bad_pop();
if {Stack::pop(s1)!=’k’) throw Bad_pop();
Stack::destroy(s1)
Stack::destroy(s2)
}