读书笔记 大规模c++程序设计           

Ch1 预备知识

typedef

typedef 不能提供类型安全

class Person
{
public:
    typedef double Inches;
    typedef double Pounds;
public:
    Person();
    void SetWeight(Pounds weight);
    void getHeight(Inches height);
};

void f (const Person& person){
Person::Inches height = person.getHeight();
person.SetWeight(height); // 这里不会因为 height 的类型不是 Pounds 而报错 }

typedef 的用途

Assert

开发工作完成后,设置preprocess 预处理 NDEBUG,可以将所有的 assert 语句都去掉。 注意:assert 中应该只判断不要操作对象。

class String
{
public:
    enum {DEFAULT_SIZE = 8};
    char *d_array_p;
    int d_size;
    int d_length;
public:
    String();
};

String::String()
{
    assert(d_array_p = new char[d_size]); // 错误: assert 中应该只判断
                                          // 不要操作对象,否则会使 prod
                                          // 的版本和 debug 的版本行为不
                                          // 同。因为 prod 版 用 NDEBUG
                                          // 去掉了所有 assert.


    // 可以这样写
    d_array_p = new char[d_size];
    assert(d_array_p);
 }

Coding style 编码风格

Variable member 的命名

其他知识点: 类 member variable 代表对象的状态,改变他们,就是改变对象的状态

类的 method member 的排列顺序

按照功能排列 methods, 如示例代码, 每组将methods 按字母顺序排列

    class Car
    {
        // 按照功能排列 methods
     public:
        // CREATORS 生成和取消对象 
        Car(int cost = 0);
        Car(const Car& car );
        ~Car();

        // MANIPULATION 就是 non const method members 
        // 将methods 按字母顺序排列
        Car& operator=(const Car& car);
        void addFuel(double numberOfGallons);
        void drive(double deltaGasPedal);
        void turn(double angleInDegree);

        // ACCESSORS 都是 const method members
        double getFuel() const;
        double getRPMs() const;
        double getSpeed() const;
    }; 不要将 getXXX() setXXX() 排在一起。这样容易暴露 XXX(variable member)的行为。

迭代器 Iterator

看下面的例子:

class IntSet
{
public:
    // DATA
    intSetLink *d_root_p; // root of a linked list of integers

    // FRIENDS
    friend intSetIter;

private:
    // NOT IMPLEMENTED
    IntSet(const IntSet&);
        // 禁止 code client 通过拷贝构造 IntSet
    IntSet& operator= (const IntSet&);
        // 禁止将一个 IntSet 赋值给另一个 IntSet
public:
    // 允许创建,销毁和添加 int 到 IntSet,
    // 允许检查关系
    // CREATORS
    IntSet();
        // Create an empty set of integers
    ~IntSet();
        // Destroy this set
    // MANIPULATORS
    void add(int i);
        // Add an integer to this set. If the given integer is
        // already present, this operation has no effect.
    // ACCESSORS
    int isMember(int i) const;
        // Return 1 if integer i is a member of the set
        // and 0 otherwise

}; ## 逻辑设计表示法

常用的逻辑设计符号,用来表示逻辑实体之间的关系。

逻辑设计符号

圆角矩形表示逻辑实体: class, struct, union

长方形表示物理实体: object

常用的三种逻辑符号:

public 继承, 箭头表示依赖的方向, D 指向 B.

Uses-in-interface 的意思是说,一个函数的 signature 或者 返回类型中使用了某个 class/type。或者在类的接口 public member methods 使用了某个 class/type;

Uses in the implementation 的意思是,一个函数的定义中涉及了一个类型。分三种情况:

下面的代码中,operator == 对 IntSet 有 use-in-interface 的依赖关系,对 IntSet 有 use-in-implementation 的依赖

int operator ==(const IntSet& left, const IntSet& right){
    IntSetIter lit(left);
    IntSetIter rit(right);
    for(; lit && rit; ++lit, ++rit){
        if(lit() != rit())
            return 0;
    }
    // At least one of lit and rit now evaluates to 0
    return lit == rit;
}

Uses-in-the-implementation 的具体形式

       class Judge;         void Crook::bribe() { Judge *bad = 0; // Crook use Judge }

继承和分层 (layering)

layering 的定义:如果一个类A在其 implementation 中使用了另一个类型B (hasA, HoldsA,或者 A 由 B 组成),则类A基于类型B,类型B所在的 layer 位于类 A 所在 layer 之下. 我们通常不能通过高层的接口来访问底层的对象。也就是 B 不应该出现在 A 的接口中。B 是 A 内部的实现细节。

例子, Person hasA heart, liver, brain, 但是 Person 在工作的时候,不需要将 heart, liver, brain 暴露在 interface 上。

最小化

用不到的功能不实现。