• 第一部分 对象和作用域(C++ In Action学习总结)


    1,全局作用域与局部作用域

    #include <iostream>
    
    using namespace std;
    
    class World
    {
    public:
        World(int id)
                : _identifier(id)
        {
            cout << "Hello:" << _identifier << endl;
        }
    
        ~World()
        {
            std::cout << "Good Bye:" << _identifier << endl;
        }
    
    private:
        const int _identifier;  // const 变量必须在前导时进行初始化,只有一次初始化的机会,后续再也不能改变
    };
    
    World theWorld(1);    // 全局作用域,将初始化和析构theWorld对象
    
    int main()
    {
        World worldSmall(2);
        for(int i = 3; i < 5; i++)
        {
            World aWorld(i);
        }
        return 0;
    }
    
    

    输出结果:

    Hello:1		先初始化全局作用域
    Hello:2		从上到下依次初始化
    Hello:3
    Good Bye:3
    Hello:4
    Good Bye:4
    Good Bye:2
    Good Bye:1
    

    2, 嵌入对象(has-a)

    #include <iostream>
    
    using namespace std;
    
    class Matter
    {
    public:
        Matter(int id) : _identifier(id)
        {
            cout << "Matter in:" << _identifier << endl;
        }
    
        ~Matter()
        {
            cout << "Matter leave:" << _identifier << endl;
        }
    
    private:
        const int _identifier;
    };
    
    class World
    {
    public:
        World(int id) : _matter(_identifier), _identifier(id)
        {
            cout << "World in:" << _identifier << endl;
        }
    
        ~World()
        {
            std::cout << "World leave:" << _identifier << endl;
        }
    
    private:
        const int _identifier;  // const 变量必须在前导时进行初始化
        const Matter _matter;   // 嵌入类型对象 matter
    };
    
    World theWorld(1);    // 全局作用域,将初始化和析构theWorld对象
    
    int main()
    {
        World worldSmall(2);
        return 0;
    }
    
    

    输出结果:

    Matter in:1
    World in:1
    Matter in:2
    World in:2
    World leave:2
    Matter leave:2
    World leave:1
    Matter leave:1
    
    2.1,初始化顺序

    数据成员按照他们在类定义中的出现顺序进行初始化,和前导顺序无关,上例中,因为_identifier在_matter前面出现,先初始化identifier,在初始化_matter。

    3,继承

    #include <iostream>
    
    using namespace std;
    
    class Book
    {
    public:
        Book(int size):_size(size)
        {
            cout << "Init book size is " << _size << endl;
        }
    
        ~Book()
        {
            cout << "Destroy book size is " << _size << endl;
        }
    
    private:
        const int _size;     // 尺寸
    };
    
    class MathBook : public Book
    {
    public:
        MathBook(int size, string color):_color(color), Book(size)
        {
            cout << "Init MathBook Color is " << _color << endl;
        }
        ~MathBook()
        {
            cout << "Destroy MathBook Color is " << _color << endl;
        }
    
    private:
        const string _color;    // 书的颜色
    };
    
    MathBook mb1(1,"yellow");
    int main()
    {
        MathBook mb2(2, "green");
        return 0;
    }
    
    
    3.1, 构造顺序

    首先完全构造基类,再构造派生类。

    前导初始化中的顺序是没有任何意义的。

    派生类构造顺序一般是:嵌入体 => 构造函数中的显示代码

    4,成员函数作用域

    #include <iostream>
    
    using namespace std;
    
    class InputNum
    {
    public:
        InputNum(char msg[])
        {
            cout << msg;
            cin >> _num;
        }
        int GetValue() const    // 该方法没有改变对象的状态,并且不允许改变数据的操作出现,如赋值,自增,自减。
        {
            return _num;
        }
        void AddInput(char msg[])
        {
            InputNum aNum(msg);
            _num = _num + aNum.GetValue();
        }
    
    private:
        int _num;
    };
    
    const char SumString[] = "The num is ";
    
    int main()
    {
        InputNum num("Enter number ");
        num.AddInput("Add one ");
        num.AddInput("Add another ");
        cout << SumString << num.GetValue() << endl;
        return 0;
    }
    
    
    4.1,总结:

    成员函数,析构函数, 构造函数,都会形成一个单独的本地作用域。

    使用成员函数访问数据成员没有运行时开销。因为内联函数的原因。

    5,抽象数据类型(文件,非内联成员函数,断言)

    • stack.h(定义接口)。
    /**
     * 接口文件必须包括:
     * 类的定义,
     * 指定所有的数据成员
     * 声明成员函数
     */
    
    const int maxStack = 16;
    class IStack
    {
    public:
        IStack():_top(0){}
        void Push(int i);   // 将i压入堆栈
        int Pop();     // 将堆栈顶上的元素弹出,并返回
        int Size();     // 返回栈中元素
        int Top();      // 返回栈顶元素,不返回
    
    private:
        int _arr [maxStack];
        int _top;
    };
    
    
    • stack.h(函数定义)
    #include "stack.h"
    #include <cassert>
    #include <iostream>
    
    // 通过NDEBUG=1编译去掉断言
    void IStack::Push(int i)
    {
        assert(_top < maxStack);
        _arr [_top++] = i;
    }
    
    int IStack::Pop()
    {
        assert(_top > 0);
        return _arr[--_top];
    }
    
    int IStack::Size()
    {
        return _top;
    }
    int IStack::Top()
    {
        assert(_top != 0);
        return _arr[_top-1];
    }
    
    
    • main.cpp
    #include <iostream>
    #include "stack.h"
    
    using namespace std;
    
    int main()
    {
        IStack stack;
        stack.Push(1);
        stack.Push(2);
        stack.Push(10);
        cout << stack.Size() << endl;
        cout << stack.Top() << endl;
        cout << stack.Pop() << endl;
        cout << stack.Pop() << endl;
        cout << stack.Top() << endl;
        return 0;
    }
    
    
    • 输出结果
    3
    10
    10
    2
    1
    
    5.1, 断言assert(一个宏)

    如果没有定义NDEBUG,编译时就将断言完全关闭,提高程序速度。

    没有定义时,断言就会检查它参数的逻辑正确性,即检查是否为一个非零值,用来判断参数的真实性。

    用来区别对待调试版本和发行版本。

    当断言参数为假时,断言在执行时触发,打印一条指定源文件名,行号和不满足条件的信息。断言是一个调试工具。断言失败时,往往意味着程序中存在漏洞。

    Assertion failed!
    
    Program: D:CodeCppstudy_classcmake-build-debugstudy_class.exe
    File: D:CodeCppstudy_classstack.cpp, Line 14
    
    Expression: _top > 0
    
    5.2,关于内联函数

    编译器试图将函数的实际代码插入到调用它的地方,依次来提高效率。

    定义嵌入类中的成员函数由编译器自动变为内联。

    将成员函数放到类外,将自动变为非内联。此时要在函数定义前面添加inline来告诉编译器变为内联。

    内联只会适用于简单的情况,如函数中只有一条语句,没有复杂的程序结构(循环等),复杂结构即使使用inline和嵌入类中也会自动变为非内联。

  • 相关阅读:
    10g full join 优化
    推荐C++程序员阅读《CLR via C#》
    密码安全之动态盐
    徒弟们对话,遇到sb领导,离职吧
    hdu 1698 线段数的区间更新 以及延迟更新
    嗯。。 差不多是第一道自己搞出的状态方程 hdu4502 有一点点变形的背包
    嗯 第二道线段树题目 对左右节点和下标有了更深的理解 hdu1556
    hdu 4501三重包问题
    入手线段树 hdu1754
    hdu 5672 尺取还是挺好用的
  • 原文地址:https://www.cnblogs.com/jlxa162hhf/p/14161220.html
Copyright © 2020-2023  润新知