zoukankan      html  css  js  c++  java
  • 《C++ Primer》未理解知识点备忘

    本博文记录阅读《C++ Primer》过程中遇到的未理解知识点,便于日后回头有针对性的攻克。

    教材:《C++ Primer中文第四版(非扫描)》

    1.第369页有这么一句“。 正如前面第 7.8 节所提到的,当形参以副本传递时,不能基于形参是否为 const 来实现重载。”

    提示:可以下去7.8节去了解一下

    次日即2013-03-31问题解决详细:

    理解了下面这段代码,就理解了上面这个问题:

    1      Record lookup(Phone); 
    2      Record lookup(const Phone); // redeclaration 

    《C++ Primer》中是这样解释的:

    这“一对的区别仅在于是否将形参定义为 const。 这种差异并不影响传递至函数的对象; 第二个函数声明被视为第一个的重复声明。 其原因在于实参传递的方式。复制形参时并不考虑形参是否为 const——函数操纵的只是副本。 函数的无法修改实参。 结果, 既可将 const 对象传递给 const 形参, 也可传递给非 const 形参,这两种形参并无本质区别。”

    “值得注意的是,形参与 const 形参的等价性仅适用于非引用形参。有 const 引用形参的函数与有非 const 引用形参的函数是不同的。类似地,如果函数带有指向 const 类型的指针形参, 则与带有指向相同类型的非 const 对象的指针形参的函数不相同。”

    个人感悟:

    其实,这个问题本质上还是const特性和调用函数参数的传递方式

    __________________________________________________________________________________

    2.有这么一种变量定义形式:

    1 string::size_type pos = dept.find_first_not_of(numbers);

    其中,pos被定义为string::size_type类型,size_type这个类型本身理解,它归属于string这也理解,但为什么用的是“::”的作用域限定符而不是“.”点操作符,类似的使用比较多,而且未来写代码的时候估计会经常用到,所以有必要搞清楚。

    提醒与思考:

      可以看看string类型的源代码,看看其中size_type与其它成员有何不同,是不是静态static的,或者从定义变量的角度去考虑一下。

      有一点是肯定的,string不是对象只是类型,所以“.”点操作符不能使用,但哪些成员是可以使用作用域限定符的,通常应该在什么时候用,可以查看源代码、搜索答案或上机测试,这个知识点牵扯到的内容较丰富,搞清楚后有必要单独写一篇随笔。

    2013-04-18

    另外,类似用法在《C++ Primer》第499页也有一例:

    set<TextQuery::line_no> locs = tq.run_query(s);

     这里可以记录一点:“TextQuery”是自定义的类,line_no并不是“TextQuery”的成员,它只是在类中typedef的一个别名,如下:

     typedef std::vector<std::string>::size_type line_no;  

     类似使用中有一个容易理解的例子,看能不能辅助理解其它:

     map<string, set<line_no> >::const_iterator loc = word_map.find(query_word); 

     这里面的作用域限定符后跟的是一个iterator,这个iterator可以指向多种容器、可以指向含不同种类型pair元素的的对象,但是,因为目前要用到指向“map<string, set<line_no> >”对象的迭代器,也就是说:map的键类型为string,值类型为set<line_no>,用“::”来限定iterator,就完成了这种指定。 

    2013-05-01

    在《C++ Primer》第564页找到一句相关的解释:“一些成员使用成员访问操作符来访问,另一些直接通过类使用作用域操作符(::)来访问。一般的数据或函数成员必须通过对象来访问。定义类型的成员,如 Screen::index,使用作用域操作符来访问。”,其中,index是以下面这样的形式出现在类中的:

    1      class Screen { 
    2      public: 
    3          // interface member functions 
    4          typedef std::string::size_type index; 
    5      private: 
    6          std::string contents; 
    7          index cursor; 
    8          index height, width; 
    9      };  

     从这个例子可以看出,index其实是一个类型。

    2013-05-02

    《C++ Primer》592页中另一句相关的用法:

    “可以通过作用域操作符从类直接调用 static 成员,或者通过对象、引用或指向该类类型对象的指针间接调用。”

    _________________________________________________________________________________

     3.  495页起的“10.6. 容器的综合应用:文本查询程序 ”相关讲解中,有个别地方不理解,关键没搞清楚题意及代码意思,改天专门看一下。本题的涉及面很广:内置类型、string、标准IO库、容器的vector、map、set组合使用,几乎涵盖了前十章的知识点。

    解决:随后在看成员函数的定义的时候问题基本解决。关键点在下面这段代码:

    1      // read input file: store each line as element in lines_of_text 
    2      void TextQuery::store_file(ifstream &is) 
    3      { 
    4          string textline; 
    5          while (getline(is, textline)) 
    6             lines_of_text.push_back(textline); 
    7      } 
    8  

    以及class TextQuery中map的定义:

     std::map< std::string, std::set<line_no> > word_map;

     其它一些未理解知识点提醒:

    另外注意理解下面这几行:

        typedef std::vector<std::string>::size_type line_no; 
    
        std::vector<std::string> lines_of_text;
        std::map< std::string, std::set<line_no> > word_map; 

     解决:次日即2013-04-18问题解决如下:

    上面三行代码是生命,首先要理解透map的pair对象的两个数据类型是“string和set”,set是一个容器,可以存放多个元素,另外:

    word_map[word].insert(line_num); 

    这行代码首先使用“word”对word_map进行下标操作,返回的是与word键关联的一个set集,因为set集是以行号为元素,所以,只有行号改变后,对同一个word进行插入才会添加set元素,这就理解了“如果某个单词在同一行中重复出现,那么 insert 函数的调用将不做任何操作。”及一些相关的其它操作

    对于这个程序,还有下面这些代码起初看到时懵了一下:

         if (loc == word_map.end()) 
             return set<line_no>(); // not found, return empty set 

    第一次看到这种return方式,如果不是后来看到“return set<line_no>”后面还有括号,估计这两行代码无论如何想不通。在MSDN等地方查看,确实有一个“set()”的构造函数,但代码中这种使用格式怪怪的,没有搜到更多满意资料,以后可以回头看看。

    2013-04-30

    这一点在后来的代码中有类似的出现,且相对容易理解(《C++ Primer》530页):

    1      // find first element in a comma-separated list 
    2      string::iterator comma = find(line.begin(), line.end(), ','); 
    3      cout << string(line.begin(), comma) << endl;

    代码展开后的最后一部分如下:

    1           line_nums::const_iterator it = locs.begin(); 
    2           for ( ; it != locs.end(); ++it) { 
    3               cout << "\t(line " 
    4                    // don't confound user with text lines starting at 0 
    5                    << (*it) + 1 << ") " 
    6                    << file.text_line(*it) << endl; 

    1    string TextQuery::text_line(line_no line) const 
    2    { 
    3        if (line < lines_of_text.size()) 
    4            return lines_of_text[line]; 
    5        throw std::out_of_range("line number out of range"); 
    6    } 

    其实就是对set遍历并输出set没个元素对应的行的字符串内容,至此,全部理解,不过,此题经典,以后实际开发时遇到其中提到的知识点可以回来看看,在思考一下。最后提醒一句,想理解这段代码,最好把所有代码复制到一个文件中整体来看,在书上那种一段代码一段文字隔开,只是出于方便讲解的考虑。

     4.《C++ Primer》的算法这一章多次提到“算法”和“容器操作”是有区别的,例如:算法不直接修改容器的大小。如果需要添加或删除元素,则必须使用容器操作。 有必要将这两个概念做个对比和区分,另外:《容器提供的常用操作或算法》的博文中记录了一些操作和算法,有必要将他们区别成两个表格,因为本质不同。

     其实二者在使用形式上有很明显的一点不同,操作使用成员操作符(即“点操作符”)来调用的例如:ivec.begin();而算法是使用函数的形式,例如:“unique(words.begin(), words.end())”

    2013-05-02

    5.《C++ Primer》第594页有这么一段话:

    “因为 static 成员不是任何对象的组成部分,所以 static 成员函数不能被声明为 const。毕竟,将成员函数声明为 const 就是承诺不会修改该函数所属的对象。 最后, static 成员函数也不能被声明为虚函数。 我们将在第 15.2.4 节学习虚函数。”

    没能理解这句话的逻辑

    6.《C++ Primer》第652页有这么一段话:没能够理解。

    “但是,如果将 operator< 定义为对 isbn 的比较,该定义将与前面 == 的定义不相容。。如果有两个针对同一 ISBN 的事务,其中任意一个都不会小于另一个,然而,如果这两个对象中的销售数据不同,则它们就不相等。”

    问题提醒:为什么==和<操作符定义不相容

    2013-05-09

     7.类型转换与自动提升相关章节人站看一遍,相关知识点以后可能会经常用到,而且易于混淆,写成随笔归入终结混淆分类

     2013-05-17

    8.这个是一个易错点,之前不是这么认为的,尚未上机测试

    这段代码:

    1      class Disc_item : public Item_base { 
    2      public: 
    3          std::pair<size_t, double> discount_policy() const 
    4              { return std::make_pair(quantity, discount); } 
    5          // other members as before 
    6      };
    1      Bulk_item bulk; 
    2      Bulk_item *bulkP = &bulk;  // ok: static and dynamic types are the same 
    3      Item_base *itemP = &bulk;  // ok: static and dynamic types differ 
    4      bulkP->discount_policy();  // ok: bulkP has type Bulk_item* 
    5      itemP->discount_policy();  // error: itemP has type Item_base* 

    是为了说明一个问题,在多层派生中,假设分别有1 2 3共三层,在第二层内定义的函数,使用基类的指针进行动态绑定时容易出错,这时候要思考一个问题:动态绑定是不是只能调用基类中定义过的虚函数;还得测试一下,如果1层中定义了一个非虚函数,在2层中有一个同名函数,但不是虚函数,这时候,如果用1层的指针进行动态绑定会发生什么情况;回头上机测试一下 

     9

    2013-05-21

    15.9.“再谈文本查询示例”    这一节有必要回头认真看一下,尤其是例题代码的设计思想和句柄类的使用

  • 相关阅读:
    pycharm的常规使用
    python-引用/模块
    6-4 函数
    5-21文件的操作
    5-21python数据类型
    python-基础
    5-7接口测试工具之jmeter的使用
    接口测试基础
    把命令结果作为变量赋值
    shell变量子串
  • 原文地址:https://www.cnblogs.com/tingshuixuan2012/p/2991078.html
Copyright © 2011-2022 走看看