【C++语言99个常见编程错误】第1章 基础问题

来源:互联网 发布:网络安全保卫局副局长 编辑:程序博客网 时间:2024/06/09 14:18
1章 基础问题

过分积极的注释

画蛇添足,最有效率的代码就是根本不存在的代码,最好的注释就是根本用不着注释

如果某种结构(函数、类型的公开接口)能被塞到一页里,三四十行,它就容易理解

一个声名狼藉的编码实践就是把更改日志作为注释插入到源文件的头部或尾部

想不用注释,就要遵循简单易行的、定义良好的命名习惯

函数声明中形式参数的名字尤其重要

减少注释的办法就是采用标注库中的、或尽人皆知的组件

注释不应该维护显而易见的事儿,或把别的地方已经说清楚的东西再重复一遍

幻数  字面常量

字面常量的主要问题是它们没有(抽象)语义

在其所在作用域有着明确含义的枚举常量,不占空间,也没有任何运行期成本

字面常量有一个坏处就是它会以意想不到的方式降低它所代表的类型那个的精度

使用枚举常量或初始化了的具名常量代替幻数

全局变量

全局变量阻碍了代码重用,增加了模块的耦合

仅仅把对于值的访问加上函数形式的包装,就获得了可贵的可扩展性

未能区分函数重载和形参默认值

函数重载和形参默认值的语法很类似,不要混淆,默认参数,就可以不写参数了。

重载用于一组抽象意义相同,但实现不同的函数。形参默认值处于简化,为函数提供更简洁的接口

对引用的认识误区

引用只是其初始化物的别名,引用是没有地址的,甚至有可能不占任何存储

所以,声明引用的引用,指向引用的指针,引用的数组,都是不合法的

在引用类型前面加上constvolatile是可以的,但会忽略

指向数组的引用保留了数组尺寸信息,而指针则不保留

强制类型转换的结果是右值,而不是左值

对常量的认识误区

字面常量没有地址,永远不可能改变其值

如果把左值理解为“能放置值的地方”,右值就是没有与之相关的地址的值

const int *p2 = &ci, const描述了通过ip2ci的操作的约束,而不是对于ci的一般操作的约束

无视基础语言的精妙

int x = 1;

switch(x)

{

default:cout<<"default" <<endl;

case 0: cout<<0<<endl;break;

case 2:cout<<2<<endl;

}

输出为default 0

switch语句的任何地方都可以用case标记,而且不一定要在一个嵌套里

switch(expr)

    default:

    if(cond1)

{

    case 1: stmt1;

    case 2: stmt2;

}

else

{

    if(cond2)

    case 3:stmt3;

    else

    case 0:;

}

例子

switch(1)

    default:

    if(0)

{

    case 1: cout << 1 << endl;

if(0)

    case 2: cout << 2 << endl;

}

else

{

    if(1)

    case 3: cout << 3 << endl;

    else

    case 0: cout << 0 << endl;;

}

输出为 1

bool r = a < b; 来代替if语句

条件运算符来代替if else

未能区分可访问性和可见性

C++语言压根儿就没有实现什么数据隐藏,它实现的是访问层级。在class中具有protectedprivate访问层级并非不可见,只是不可访问

提供一个放置各种适当前置声明的专用头文件

class接口与实现分离,从而达到数据隐藏的效果,最好的办法是使用Bridge模式

#include<iostream>

using namespace std;

class B

{

   public:

     void g(){ cout << "B::g()" << endl; }

   private:

     virtual void f() { cout << "B::f()" << endl; }

};

class D: public B

{

   public:

     void f(){ cout << "D::f()" << endl; }

   private:

     double g;

};

int main()

{

     D *d = new D();

     d->f();

     return 0;

}

输出为D::f(),如果B *b = new D();再调用b->f()是不可行的

使用糟糕的语言

NULL符号在不同的平台上,有多种定义的方法,可移植性差,真正领会了C++精神的程序员仍然使用0

无视习惯用法

auto_ptr能够从堆上分配空间,当不可用时,自动善后

当一个auto_ptr使用另一个auto_ptr对象初始化或赋值时,源对象就终止了对它只设的从堆上分配的对象的所有权

聪明反被聪明误

a+++++b,错误,i++不是左值

a+++ ++b 正确

ptr->*m,正确

ptr-> *m,错误

遵循习惯用法,清晰的表达和一点点效率的损失好过小聪明、模棱两可和维护便利的丧失

 

原创粉丝点击