文章目录
练习18.11
what中如果抛出异常,需要try catch捕获,再调用what,一直循环,直达内存耗尽。
练习18.12
Query.h
#ifndef QUERY_H_
#define QUERY_H_
#include <string>
#include <iostream>
#include "Query_base.h"
#include "WordQuery.h"
#include "TextQuery.h"
namespace chapter15
{
class Query
{
friend Query operator~(const Query&);
friend Query operator|(const Query&, const Query&);
friend Query operator&(const Query&, const Query&);
public:
Query(const std::string&);
chapter10::QueryResult eval(const chapter10::TextQuery &t) const { return q->eval(t); }
std::string rep() const { std::cout << "Query::rep()" << std::endl; return q->rep(); }
private:
Query(std::shared_ptr<Query_base> query) : q(query) { std::cout << "Query(std::shared_ptr<Query_base> query)" << std::endl; }
std::shared_ptr<Query_base> q;
};
std::ostream& operator<<(std::ostream &os, const Query &query)
{
return os << query.rep();
}
inline Query::Query(const std::string &s) : q(new WordQuery(s)) { std::cout << "Query::Query(const std::string &s)" << std::endl; }
}
#endif
TextQuery.h
#ifndef TEXTQUERY_H_
#define TEXTQUERY_H_
#include <string>
#include <vector>
#include <map>
#include <fstream>
#include <sstream>
#include <set>
#include <memory>
#include <iostream>
#include <algorithm>
#include <iterator>
#include "StrBlob.h"
namespace chapter10
{
class QueryResult;
class TextQuery
{
public:
using line_no = std::vector<std::string>::size_type;
TextQuery(std::ifstream&);
QueryResult query(const std::string&) const;
private:
StrBlob file;
std::map<std::string, std::shared_ptr<std::set<line_no>>> word_map;
};
class QueryResult
{
friend std::ostream& print(std::ostream&, const QueryResult&);
public:
QueryResult(std::string s, std::shared_ptr<std::set<TextQuery::line_no>> p, StrBlob f) : sought(s), lines(p), file(f) { }
std::set<StrBlob::size_type>::iterator begin() const { return lines->begin(); }
std::set<StrBlob::size_type>::iterator end() const { return lines->end(); }
// std::shared_ptr<StrBlob> get_file() const { return std::make_shared<StrBlob>(file); }
const StrBlob& get_file() const { return file; }
private:
std::string sought;
std::shared_ptr<std::set<TextQuery::line_no>> lines;
StrBlob file;
};
TextQuery::TextQuery(std::ifstream &ifs)
{
std::string text_line;
while(std::getline(ifs, text_line))
{
file.push_back(text_line);
int line_number = file.size() - 1;
std::istringstream line(text_line);
std::string text_word;
while(line >> text_word)
{
std::string word;
std::copy_if(text_word.begin(), text_word.end(), std::back_inserter(word), isalpha);
// std::cout << word << std::endl;
auto &wm_lines = word_map[word];
if(!wm_lines)
wm_lines.reset(new std::set<line_no>);
wm_lines->insert(line_number);
}
}
}
QueryResult TextQuery::query(const std::string &sought) const
{
static std::shared_ptr<std::set<TextQuery::line_no>> nodata(new std::set<TextQuery::line_no>);
auto loc = word_map.find(sought);
if(loc == word_map.end())
return QueryResult(sought, nodata, file);
else
return QueryResult(sought, loc->second, file);
}
std::ostream &print(std::ostream &os, const QueryResult &qr)
{
os << qr.sought << " occurs " << qr.lines->size() << " " /*<< make_plural(qr.lines->size(), "time", "s")*/ << std::endl;
for(auto num : *qr.lines)
{
ConstStrBlobPtr p(qr.file, num);
os << "\t(line " << num + 1 << ") " << p.deref() << std::endl;
}
return os;
}
}
#endif
练习18.13
在需要在其所在的文件中可见,在其所在的文件外不可见时;
static只能用于变量与函数,不可用于用户自定义的类型。
练习18.14
namespace mathLib {
namespace MatrixLib {
class matrix { /* ... */ };
matrix operator* (const matrix &, const matrix &);
// ...
}
}
请问你应该如何在全局作用域中声明该运算符?
mathLib::MatrixLib::matrix mathLib::MatrixLib::operator*(const matrix&, const matrix&);
练习18.15
using指示引入的名字的作用域远比using声明引入的名字的作用域复杂。它具有将命名空间成员提升到包含命名空间本身和using指示的最近作用域的能力。对于using声明来说,我们指示简单地领名字在局部作用域有效。
using指示是令整个命名空间的所有内容变得有效。通常情况下,命名空间中会含有一些不能出现在局部作用域的定义,因此using指示一般被看作是出现在最近的外层作用域中。
练习18.16
namespace Exercise {
int ivar = 0;
double dvar = 0;
const int limit = 1000;
}
int ivar = 0;
//位置1
void main() {
//位置2
double dvar = 3.1416;
int iobj = limit + 1;
++ivar;
++::ivar;
}
namespace Exercise{
int ivar = 0;
double dvar = 0;
const int limit = 1000;
}
int ivar = 0;
using Exercise::ivar; //1
using Exercise::dvar;
using Exercise::limit;
// using namespace Exercise; //3
void mainp(){
// using Exercise::ivar; //2
// using Exercise::dvar;
// using Exercise::limit;
// using namespace Exercise; //4
double dvar = 3.1416;
int iobj = limit + 1;
++ivar;
++::ivar;
}
int main()
{
return 0;
}
练习18.17
练习18.18
void swap(T v1, T v2)
{
using std::swap;
swap(v1.mem1, v2.mem1);
//交换类型的其他成员
}
前者使用string版本的swap;后者使用实例化为int的swap。
练习18.19
将只使用标准库的swap,如果v1.mem1和v2.mem1为用户自定义类型,将无法使用用户定义的针对该类型的swap。
练习18.20
namespace primerLib {
void compute();
void compute(const void *);
}
using primerLib::compute;
void compute(int);
void compute(double, double = 3.4);
void compute(char*, char* = 0);
void f()
{
compute(0);
}
候选函数:全部;
可行函数:
void compute(int)(最佳匹配)
void compute(double, double = 3.4)(int->double)
void compute(char*, char* = 0)(0->nullptr)
void compute(const void *)(0->nullptr)
改变后:
void compute(const void *)为最佳匹配。