《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 >”对象的迭代器,也就是说:map的键类型为string,值类型为set,用“::”来限定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 成员,或者通过对象、引用或指向该类类型对象的指针间接调用。”


  1. 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方式,如果不是后来看到“returnset”后面还有括号,估计这两行代码无论如何想不通。在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.“再谈文本查询示例” 这一节有必要回头认真看一下,尤其是例题代码的设计思想和句柄类的使用

原文链接: https://www.cnblogs.com/tingshuixuan2012/archive/2013/03/30/2991078.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/82618

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月9日 下午8:41
下一篇 2023年2月9日 下午8:41

相关推荐