18.1
*p解引用后是r,所以两者都是range_error对象
因为是throw p,如果没有匹配的catch,那么将调用terminate,程序将终止
18.2
v是vector对象,将调用自己的析构函数
指针p被释放,但是p所指向的内存将丢失
调用自己的析构函数,关闭文件
18.3
1、使用类对象的方法,创建一个包含一个int*的类,在析构函数进行delete文件指针
- class intAr
- {
- int *p=nullptr;
- public:
- intAr(size_t n):p(new int[n]){}
- ~intAr()
- {
- delete[]p;
- }
- }
intAr p(v.size());,那么p对象就可以在发生异常时调用析构函数delete所分配的内存了
2、使用智能指针,自动控制
- std::shared_ptr<int> p(new int[v.size()], [](int *p) { delete[] p; });
使用lambda表达式创建一个函数对象给智能指针的构造函数,在发生异常时自动调用并delete内存
18.4
第一个catch就是基类,那么所有该基类的派生类都可以匹配,因为不是引用或指针,那么将丢弃基类以为的部分
第二个catch也是,runtime_error派生出overflow_error,能匹配runtime_error和voerflw_error,所以当发生overflow_error异常时总是使用runtime_error
- try {
-
- }
- catch (overflow_error e)
- {
-
- }
- catch (const runtime_error &r)
- {
-
- }
- catch (exception e)
- {
-
- }
18.5
- #include <iostream>
- #include <cstdlib>
- int main()
- {
- using namespace std;
- try {
-
- }
- catch (overflow_error e)
- {
- cout << e.what();
- abort();
- }
- catch (underflow_error u)
- {
- cout << u.what();
- abort();
- }
- catch (range_error r)
- {
- cout << r.what();
- abort();
- }
- catch (domain_error d)
- {
- cout << d.what();
- abort();
- }
- catch (invalid_argument i)
- {
- cout << i.what();
- abort();
- }
- catch (out_of_range o)
- {
- cout << o.what();
- abort();
- }
- catch (length_error l)
- {
- cout << l.what();
- abort();
- }
- catch (runtime_error r)
- {
- cout << r.what();
- abort();
- }
- catch (logic_error l)
- {
- cout << l.what();
- abort();
- }
- catch (bad_alloc b)
- {
- cout << b.what();
- abort();
- }
- catch (bad_alloc b)
- {
- cout << b.what();
- abort();
- }
- catch (exception e)
- {
- cout << e.what();
- abort();
- }
-
- return 0;
- }
18.6
a、throw &exceptionType();
b、任何异常都行
c、throw int();
应该没错..
18.7
- #pragma once
- #include <iostream>
- #include <string>
- #include <vector>
- #include <initializer_list>
- #include <memory> //shared_ptr
- template<typename T> class Blob;
- template<typename T> class BlobPtr;
- template<typename T> bool operator==(const Blob<T>&, const Blob<T>&);
- template<typename T>
- class Blob
- {
- public:
- friend class BlobPtr<T>;
- friend bool operator==<T>(const Blob &l, const Blob &r);
- typedef T value_type;
- typedef typename std::vector<T>::size_type size_type;
- Blob();
- Blob(std::initializer_list<T> il);
- template<class U>
- Blob(U b, U e);
- size_type size()const {
- return data->size();
- }
- bool empty()const {
- return data->empty();
- }
- void push_back(const T &t) {
- data->push_back(t);
- }
- void push_back(T &&t) {
- data->push_back(std::move(t));
- }
- void pop_back();
- T &back();
- T &operator[](size_type i);
- private:
- std::shared_ptr<std::vector<T>> data;
- void check(size_type i, const std::string &msg)const;
- };
-
- template<typename T>
- void Blob<T>::check(size_type i, const std::string &msg)const {
- if (i >= data->size())
- throw std::out_of_range(msg);
- }
- template<typename T>
- T &Blob<T>::back() {
- check(0, "back on empty Blob");
- return data->back();
- }
- template<typename T>
- T &Blob<T>::operator[](size_type i) {
- check(i, "subscript out range");
- return (*data)[i];
- }
- template<typename T>
- void Blob<T>::pop_back() {
- check(0, "pop_back on empty Blob");
- data->pop_back();
- }
- template<typename T>
- Blob<T>::Blob() try:data(std::make_shared<std::vector<T>>()) {
- }
- catch (const std::bad_alloc &e) {
- std::cerr << e.what() << std::endl;
- }
- template<typename T>
- Blob<T>::Blob(std::initializer_list<T> il) try : data(std::make_shared<std::vector<T>>(il)) {
- }
- catch (const std::bad_alloc &e) {
- std::cerr << e.what() << std::endl;
- }
-
- template<typename T>
- bool operator==(const Blob<T> &l, const Blob<T> &r) {
- if (l.data != r.data)
- return false;
- return true;
- }
-
- template<class T>
- template<class U>
- Blob<T>::Blob(U b, U e) :data(std::make_shared < std::vector<T>>(b, e)) {}
-
- #pragma once
- #include "Blob.h"
- template<typename T>
- class BlobPtr {
- public:
- BlobPtr();
- BlobPtr(Blob<T> &a, size_t sz = 0);
- T &operator*()const;
- BlobPtr &operator++();
- BlobPtr &operator--();
- private:
- std::shared_ptr<std::vector<T>> check(std::size_t i, const std::string &s)const;
- std::weak_ptr<std::vector<T>> wptr;
- std::size_t curr;
- };
- template<typename T>
- BlobPtr<T>::BlobPtr() try :curr(0) {
- }
- catch(const std::bad_alloc &e){
- std::cerr << e.what() << std::endl;
- }
-
- template<typename T>
- BlobPtr<T>::BlobPtr(Blob<T> &a, size_t sz ) try : wptr(a.data), curr(sz) {
- }
- catch (const std::bad_alloc &e) {
- std::cerr << e.what() << std::endl;
- }
-
- template<typename T>
- T &BlobPtr<T>::operator*()const {
- auto p = check(curr, "dereference past end");
- return (*p)[curr];
- }
-
- template<typename T>
- BlobPtr<T> &BlobPtr<T>::operator++() {
- ++curr;
- check(curr, "++obj error");
- return *this;
- }
-
- template<typename T>
- BlobPtr<T> &BlobPtr<T>::operator--() {
- --curr;
- if (curr < 0)
- throw std::out_of_range("--obj error");
- return *this;
- }
-
- template<typename T>
- std::shared_ptr<std::vector<T>> BlobPtr<T>::check(std::size_t i, const std::string &s)const {
- auto ret = wptr.lock();
- if (!ret)
- throw std::out_of_range("unbound BlobPtr");
- if (i >= ret->size())
- throw std::out_of_range(s);
- return ret;
- }
18.8
略,别问我为什么
18.9
- #pragma once
- #include <iostream>
- #include <string>
-
- struct out_of_stock :public std::runtime_error
- {
- explicit out_of_stock(const std::string &s) :std::runtime_error(s) {}
- };
-
- struct isbn_mismatch :public std::logic_error
- {
- explicit isbn_mismatch(const std::string &s) :std::logic_error(s) {}
- isbn_mismatch(const std::string &s, const std::string &ls, const std::string &rs)
- :std::logic_error(s), left(ls), right(rs)
- {}
- std::string left;
- std::string right;
- };
- #pragma once
- #include "error_class.h"
- class Sales_data
- {
- std::string bookNo;
- unsigned units_sold = 0;
- double revenue = 0.0;
- double avg_price() const;
- public:
- Sales_data() = default;
- Sales_data(const std::string &s) : bookNo(s) {}
- Sales_data(const std::string &s, unsigned n, double p) :
- bookNo(s), units_sold(n), revenue(p*n) {}
- explicit Sales_data(std::istream &is) { is >> *this; }
- std::string isbn() const { return bookNo; }
- Sales_data& operator+=(const Sales_data&);
- Sales_data& operator=(const std::string&);
-
- friend std::ostream &operator<<(std::ostream&, const Sales_data&);
- friend std::istream &operator>>(std::istream&, Sales_data&);
- friend Sales_data operator+(const Sales_data&, const Sales_data&);
- friend bool operator==(const Sales_data&, const Sales_data&);
- friend bool operator!=(const Sales_data&, const Sales_data&);
- friend Sales_data operator+(const Sales_data&, const Sales_data&);
- };
-
- Sales_data& Sales_data::operator+=(const Sales_data& rhs)
- {
- if (isbn() != rhs.isbn())
- throw isbn_mismatch("wrong isbns", isbn(), rhs.isbn());
- units_sold += rhs.units_sold;
- revenue += rhs.revenue;
- return *this;
- }
- Sales_data& Sales_data::operator=(const std::string &isbn)
- {
- bookNo = isbn;
- return *this;
- }
-
- inline double Sales_data::avg_price() const
- {
- if (units_sold != 0)
- return revenue / units_sold;
- else
- return revenue;
- }
-
- std::ostream& operator<<(std::ostream& os, const Sales_data& item)
- {
- os << item.bookNo << " "
- << item.units_sold << " "
- << item.revenue << " "
- << item.avg_price();
- return os;
- }
-
- std::istream& operator>>(std::istream &is, Sales_data& item)
- {
- double price = 0;
- is >> item.bookNo >> item.units_sold >> price;
- if (is)
- item.revenue = item.units_sold * price;
- else
- item = Sales_data();
- return is;
- }
- bool operator==(const Sales_data &lhs, const Sales_data &rhs)
- {
- return lhs.bookNo == rhs.bookNo &&
- lhs.units_sold == rhs.units_sold &&
- lhs.revenue == rhs.revenue;
- }
- bool operator!=(const Sales_data &lhs, const Sales_data &rhs)
- {
- return !(lhs == rhs);
- }
- Sales_data operator+(const Sales_data &lhs, const Sales_data &rhs)
- {
- Sales_data sum = lhs;
- sum += rhs;
- return sum;
- }
- #include "Sales_data.h"
-
- int main()
- {
- using namespace std;
- Sales_data item1("book1",10,23.3), item2("book2",6,66.6), sum;
- cout<<item1 + item2;
-
-
- while (cin >> item1 >> item2)
- {
- try {
- sum = item1 + item2;
- }
- catch (const isbn_mismatch &e)
- {
- cout << e.what() << ": left isbn(" << e.left << ") right isbn(" << e.right << ")" << endl;
- }
- cout << "book:\n" << sum << endl;
- }
- system("pause");
- return 0;
- }
未捕获的异常会调用terminate,导致程序结束
18.11
引用 “心不在焉”的话:
what函数一般是在catch语句中被调用的,
try/catch本来有加个保险的作用
如果what里面抛个异常,尼玛try/catch还有什么用,
难道每个catch里面都要再加个try/catch,
这不是坑人吗
https://segmentfault.com/q/1010000004968342?_ea=740379
18.12
- #pragma once
-
- #include <initializer_list>
- #include <iostream>
- #include <fstream> //ifstream
- #include <string>
- #include <vector>
- #include <sstream> //istringstream
- #include <map>
- #include <set>
- #include <memory> //shared_ptr
- namespace chapter10
- {
- class StrBlob
- {
- std::shared_ptr<std::vector<std::string>> data;
- void check(std::vector<std::string>::size_type i, const std::string &msg)const;
- public:
- using size_type = std::vector<std::string>::size_type;
- StrBlob();
- StrBlob(std::initializer_list<std::string> il);
- size_type size()const;
- bool empty()const;
- void push_back(const std::string &t);
- void pop_back();
- std::string front()const;
- std::string back()const;
- std::string &front();
- std::string &back();
- const std::shared_ptr<std::vector<std::string>> &shared_ptr()const
- {
- return data;
- }
- };
-
- class QueryResult;
- class TextQuery
- {
-
- std::shared_ptr<StrBlob> file;
- std::map<std::string, std::shared_ptr<std::set<StrBlob::size_type>>> wm;
- public:
- using line_no = std::vector<std::string>::size_type;
- TextQuery(std::ifstream &is);
- QueryResult query(const std::string &s)const;
- };
- class QueryResult
- {
- friend std::ostream &print(std::ostream &os, const QueryResult &qr);
- std::string sought;
- std::shared_ptr<std::set<StrBlob::size_type>> lines;
- std::shared_ptr<StrBlob> file;
- public:
- 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 file;
- }
- QueryResult(std::string s, const std::shared_ptr<std::set<StrBlob::size_type>> &p, std::shared_ptr<StrBlob> f) :sought(s), lines(p), file(f) {}
- };
- }
- #pragma once
-
- #include <algorithm> //set_intersection
- #include <iterator> //inserter
- #include "ch10.h"
- namespace chapter15
- {
- using namespace chapter10;
- class Query_base
- {
- friend class Query;
- virtual QueryResult eval(const TextQuery &tq)const = 0;
- virtual std::string rep()const = 0;
- protected:
- using line_no = TextQuery::line_no;
- virtual ~Query_base() = default;
- };
- class Query
- {
- friend Query operator~(const Query &qy);
- friend Query operator|(const Query &lhs, const Query &rhs);
- friend Query operator&(const Query &lhs, const Query &rhs);
- std::shared_ptr<Query_base> q;
- Query(std::shared_ptr<Query_base> qptr) :q(qptr) { std::cout << "Query(std::shared_ptr<Query_base>)\n"; }
- public:
- Query(const std::string &s);
- QueryResult eval(const TextQuery &t)const {
- return q->eval(t);
- }
- std::string rep()const {
- std::cout << "Query rep()\n";
- return q->rep();
- }
- };
- }
- #include "ch15.h"
-
- namespace chapter10
- {
- void StrBlob::check(std::vector<std::string>::size_type i, const std::string &msg)const
- {
- if (i >= data->size())
- throw std::out_of_range(msg);
- }
- StrBlob::StrBlob() :data(std::make_shared<std::vector<std::string>>())
- {}
- StrBlob::StrBlob(std::initializer_list<std::string> il) : data(std::make_shared<std::vector<std::string>>(il))
- {}
- StrBlob::size_type StrBlob::size()const
- {
- return data->size();
- }
- bool StrBlob::empty()const
- {
- return data->empty();
- }
- void StrBlob::push_back(const std::string &t)
- {
- data->push_back(t);
- }
- void StrBlob::pop_back()
- {
- check(0, "pop_push on empty StrBlob");
- data->pop_back();
- }
- std::string &StrBlob::front()
- {
- check(0, "front on empty StrBlob");
- return data->front();
- }
- std::string &StrBlob::back()
- {
- check(0, "back on empty StrBlob");
- return data->back();
- }
- std::string StrBlob::front()const
- {
- return data->front();
- }
- std::string StrBlob::back()const
- {
- return data->back();
- }
-
-
- TextQuery::TextQuery(std::ifstream &is) :file(new StrBlob())
- {
- std::string text;
- while (getline(is, text))
- {
- file->push_back(text);
- int n = file->size() - 1;
- std::istringstream line(text);
- std::string word;
- while (line >> word)
- {
- auto &lines = wm[word];
- if (!lines)
- lines.reset(new std::set<StrBlob::size_type>);
- lines->insert(n);
- }
- }
- }
-
- QueryResult TextQuery::query(const std::string &s)const
- {
- static std::shared_ptr<std::set<StrBlob::size_type>> nodata(new std::set<StrBlob::size_type>);
- auto loc = wm.find(s);
- if (loc == wm.end())
- return QueryResult(s, nodata, file);
- else
- return QueryResult(s, loc->second, file);
- }
-
- std::ostream &print(std::ostream &os, const QueryResult &qr)
- {
- os << qr.sought << " occurs " << qr.lines->size() << " " << (qr.lines->size() > 1 ? "times" : "time") << std::endl;
- for (auto x : *qr.lines)
- os << "\t(line " << x + 1 << ") " << qr.file->shared_ptr()->at(x) << std::endl;
- return os;
- }
-
- }
-
- namespace chapter15
- {
- std::ostream &operator<<(std::ostream &os, const Query query)
- {
- return os << query.rep();
- }
- class WordQuery :public Query_base
- {
- friend class Query;
- std::string query_word;
- WordQuery(const std::string s) :query_word(s) { std::cout << "WordQuery(const std::string s)\n"; }
- QueryResult eval(const TextQuery &t)const {
- return t.query(query_word);
- }
- std::string rep()const {
- std::cout << "WordQuery rep()\n";
- return query_word;
- }
- };
- Query::Query(const std::string &s) :q(new WordQuery(s)) { std::cout << "Query(const std::string &s)\n"; }
- class NotQuery :public Query_base
- {
- friend Query operator~(const Query &q);
- Query query;
- NotQuery(const Query &qy) :query(qy) { std::cout << "NotQuery(const Query &qy)\n"; }
- std::string rep()const {
- std::cout << "NotQuery rep()\n";
- return "~(" + query.rep() + ")";
- }
- QueryResult eval(const TextQuery &t)const;
- };
- Query operator~(const Query &q)
- {
- return std::shared_ptr<Query_base>(new NotQuery(q));
- }
- class BinaryQuery :public Query_base
- {
- protected:
- Query lhs, rhs;
- std::string opSym;
- BinaryQuery(const Query &l, const Query &r, std::string s) :lhs(l), rhs(r), opSym(s) { std::cout << "BinaryQuery(const Query &l, const Query &r, std::string s)\n"; }
- std::string rep()const {
- std::cout << "BinaryQuery rep()\n";
- return "(" + lhs.rep() + " " + opSym + " " + rhs.rep() + ")";
- }
- };
- class AndQuery :public BinaryQuery
- {
- friend Query operator&(const Query &lhq, const Query &rhq);
- AndQuery(const Query &left, const Query &right) :BinaryQuery(left, right, "&") { std::cout << "AndQuery(const Query &left, const Query &right)\n"; }
- QueryResult eval(const TextQuery &t)const;
- };
- Query operator&(const Query &lhs, const Query &rhs)
- {
- return std::shared_ptr<Query_base>(new AndQuery(lhs, rhs));
- }
- class OrQuery :public BinaryQuery
- {
- friend Query operator|(const Query &lhs, const Query &rhs);
- OrQuery(const Query &left, const Query &right) :BinaryQuery(left, right, "|") { std::cout << "OrQuery(const Query &left, const Query &right)\n"; }
- QueryResult eval(const TextQuery &tq)const;
- };
- Query operator|(const Query &lhs, const Query &rhs)
- {
- return std::shared_ptr<Query_base>(new OrQuery(lhs, rhs));
- }
- QueryResult OrQuery::eval(const TextQuery &tq)const
- {
- auto right = rhs.eval(tq), left = lhs.eval(tq);
- auto ret_lines = std::make_shared<std::set<line_no>>(left.begin(), left.end());
- ret_lines->insert(right.begin(), right.end());
- return QueryResult(rep(), ret_lines, left.get_file());
- }
- QueryResult AndQuery::eval(const TextQuery &t)const
- {
- auto left = lhs.eval(t), right = rhs.eval(t);
- auto ret_lines = std::make_shared<std::set<line_no>>();
- std::set_intersection(left.begin(), left.end(), right.begin(), right.end(), inserter(*ret_lines, ret_lines->begin()));
- return QueryResult(rep(), ret_lines, left.get_file());
- }
- QueryResult NotQuery::eval(const TextQuery &t)const
- {
- auto result = query.eval(t);
- auto ret_line = std::make_shared<std::set<line_no>>();
- auto beg = result.begin(), end = result.end();
- auto sz = result.get_file()->size();
- for (size_t n = 0; n != sz; ++n)
- {
- if (beg == end || *beg != n)
- ret_line->insert(n);
- else if (beg != end)
- ++beg;
- }
- return QueryResult(rep(), ret_line, result.get_file());
- }
- }
- #include "ch15.h"
- int main(int argc, char **argv)
- {
- using namespace std;
- using namespace chapter10;
- using namespace chapter15;
- ifstream ifile(argv[1]);
- print(cout, (Query("nono") | Query("ika")).eval(ifile)) << endl;
- system("pause");
- return 0;
- }
18.13
希望所定义的对象、函数、类类型或其他实体,只在程序的一小段代码中可见,这样可以进一步的缓解名字空间的冲突。
根据c++11标准,static定义静态变量的做法已取消,现在是定义一个全局的未命名的名字空间。
在未命名的名字空间中定义的变量都是静态的。
18.14
mathLib::MatrixLib::matrix mathLib::MatrixLib::operator*(matrix &a,matrix &b);
18.15
using声明:将某个成员的名字引入作用域,让该名字在该作用域可见
using指示:把名字空间的全部成员在该作用域可见
18.16、18.17
- #include <iostream>
- namespace exercise {
- int ivar = 0;
- double dvar = 0;
- const int limi = 1000;
- }
- int ivar = 0;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- int main(){
- system("pause");
- return 0;
- }
18.18
当meml是string时:
当前作用域-找到std::swap-参数string-使用string类的swap
当meml是int时:
当前作用域-找到std::swap,实例化出int型,结束
两者的不同就是string使用的是自己的swap
18.19
那么就是使用std的swap了,因为限定了是使用std的,所以string版本就直接在std里寻找,int也是直接实例化int的swap版本
18.20
1
namespace p
{
void compute();//不可行
void compute(const void *);//可行,0->NULL
}
using p::compute;
void compute(int);//可行,最佳匹配
void compute(double, double = 1.1);//可行,int->double
void compute(char*, char* = 0);//可行,0->NULL
void f()
{
compute(0);//与compute(int)版本最佳匹配
}
2
#include <iostream>
namespace p{
void compute();//不可行,不可见
void compute(const void *);//可行,0->NULL,不可见
}
void compute(int);//可行,最佳匹配
void compute(double, double = 1.1);//可行,int->double
void compute(char*, char* = 0);//可行,0->NULL
void f(){
compute(0);//与compute(int)版本最佳匹配
}
int main(){
using p::compute;
f();
return 0;
}
18.21
a、无错误,公有继承CAD,私有继承Vehicle,
b、错误,继承列表重复,多次继承List,如果是不同的List,则需要使用名字空间区分,如A():public C::List,public D::List{}
c、无错误,公有继承于标准输入与标准输出库
18.22
首先构造C,而C是派生与A和B的,所以A与B构造完后构造C
然后构造Z,而Z是派生于X与Y的,所以X与Y构造完后构造Z
所以顺序是:A->B->C->x->Y->Z->MI
18.23
无错误,所有直接基类或基类的基类都可以指向该派生类对象
#include <iostream>
using std::cout;
using std::endl;
class A {
public:
A() { cout << "A()" << endl; }
};
class B : public A {
public:
B() : A() { cout << "B()" << endl; }
};
class C : public B {
public:
C() : B() { cout << "C()" << endl; }
};
class X {
public:
X() { cout << "X()" << endl; }
};
class D : public X, public C {};
int main()
{
D *pd = new D;
X *px = pd;
A *pa = pd;
B *pb = pd;
C *pc = pd;
delete pd;
system("pause");
return 0;
}
18.24
ZooAnimal *pd=new Panda("ying_ying");
pd->print();//正确,Panda::print()
pd->cuddle();//错误,ZooAnimal无此成员
pd->highlight();//错误,ZooAnimal无此成员
delete pd;//正确,~Panda()
18.25
a、Base1::print
b、D1::print
c、D2::print
d、Base2::~Base2
e、D1::~D1
f、D2::~D2
18.26
因为MI类定义了一个自己的print成员,所以覆盖了继承的print,所以找不到接受int的print
解决方法是在MI里定义一个接受int的print,并显示调用Base1::print(int):
struct MI :public Derived, public Base2 {
void print(std::vector<double>)const;
void print(int a) { Base1::print(a); }//显示调用基类的print(int)
protected:
int *ival;
std::vector<double> dvec;
};
18.27
a、可以见的:
Base1:ival、dval、cval、print
Base2:fval、print
Derived:sval、dval、print
MI:ival、dvec、print、foo
还有在foo里定义的ival
b、是:
dval:Base1::dval、Derived::dval、自己定义的int dval
ival :MI::ival、Base1::ival
cval:Base1::cval、形参cval
print:Base1:print、Base2::print、Derived::print、MI::print
c、d、e:
void foo(double cval)
{
int dval;
dval = Base1::dval + Derived::dval;//c
Base2::fval = dvec.back();//d
Derived::sval[0] = Base1::cval;//e
}
18.28
struct Base {
void bar(int);//需要限定符
protected:
int ival;
};
struct Derived1 :public virtual Base {
void bar(char);//可直接访问,覆盖基类的bar
void foo(char);//需要限定符,否则不明确
protected:
char cval;//需要限定符,否则不明确
};
struct Derived2 :public virtual Base {
void foo(int);//需要限定符,否则不明确
protected:
int ival;//可直接访问,覆盖基类的ival
char cval;//需要限定符,否则不明确
};
struct VMI :public Derived1, public Derived2 {
void func() {
bar(4);//Derived1
Base::bar(4);//Base
Derived1::foo('a');//Derived1
Derived2::foo(4);//Derived2
auto t1 = ival;//Derived2
t1 = Base::ival;//Base
auto t2 = Derived1::cval;
t2 = Derived2::cval;
}
};
18.29
a、
Class
Base
D1
D2
MI
Class(与Base中的class不相同,独立,也就是说Final继承两个Class)
b、与构造顺序相反:Class(最外层的)->MI->D2-D1->Base->Class(Base的基类)
c、
(a)、错误,Class是Base的基类,而pb是Base类
(b)、正确,基类Class可以指向所有子类
(c)、错误、pb是Base类,MI是Base的子类
(d)、正确、D2是MI的基类
18.30
class Class {};
class Base :public Class {
protected:
int ival;
public:
Base() :ival(0),Class() {};
Base(const Base &b) = default;
Base(int a) :ival(a),Class() {}
};
class D1 :public virtual Base {
public:
D1() :Base() {}
D1(const D1 &b) = default;
D1(int a) :Base(a) {}
};
class D2 :public virtual Base {
public:
D2() :Base() {}
D2(const D2 &b) = default;
D2(int a) :Base(a) {}
};
class MI :public D1, public D2 {
public:
MI() {}
MI(const MI &m) :Base(m), D1(m), D2(m) {}
MI(int i) :Base(i), D1(i), D2(i) {}
};
class Final :public MI, public Class {
public:
Final() {}
Final(const Final &f) : Base(f), MI(f), Class() {}
Final(int i) : Base(i), Class() {}
};
2016年4月25日02:31:04