C++ Primer Chapter 18 作者: rin 时间: October 15, 2021 分类: C++ 评论 # Ch18 ## 18.1 Exception handling Exceptions: seperate problem detection from problem resolution - Thrown expression & current call chain -> determine which handler - if a dtor wants to throw exceptions, it should handle them locally, or the program will be terminated. - When search for `catch`, the *first* matched one is selected, not the best one. - Thus catch clauses with class types must be orderd from the *most* derived one to *least* one. - Conversions (between exception and "a catch exception declaration") only allowed when: 1. from *non-const* to *const* 2. from *derived* to *base* 3. *array*/*function* to *pointer* ### function `try` block - `try` is before `: [init list]` - will catch exceptions both in *init list* and *ctor body* - An *implict* `throw` will be there, thus we HAVE to catch again in the outter scope - (thus it seems useless) ```c++ // function try block in Class struct A { A(int v) try : a(v) { throw exception(); } catch(exception &e) { cout << e.what() << endl; // implicit "throw;" here } int a; }; // in ordinary function void func() try { throw "ordinary func throws"; } catch(const char *s) { cout << s << endl; } // Notice: parameter here must be `const char*` to recieve the thrown c-str // or there will be a runtime error (not a compile-time error) int main() { func(); // must handle the rethrown exception try { A a(1); } catch(exception &e) { cout << e.what() << endl; } return 0; } ``` ## 18.2 Namespaces 1. `using` Declaration: `using std::cin` 2. `using` Directive: `using namespace std` - Inside a class can only `using` members of its (direct or not) *base class*: ```c++ using std::cout; struct A{ int v=0; }; struct B{ int v = 1; // using std::cin; // NO, not class // using A::v; // NO, not base // using namespace xxx; // NO, for `using` Directive either }; struct C: public B { using B::v; // OK `using` base class members C() { cout << v << '\n';} // 1 }; ``` ## 18.3 Multiple and Virtual Inheritance ### 18.3.2 Conversion ```c++ // D1 -> A,B // D2 -> C -> A struct A {}; struct B {}; struct D1 : A,B {}; struct C : A{}; struct D2 : C {}; void func(A &a); // func1 void func(B &b); // func2 void func(C &c); // func3 int main() { D1 d1; D2 d2; func(d1); // Ambiguous between 1 & 2 func(d2); // OK, 3, not 1 } ```
C++ Primer Chapter 15 OOP 作者: rin 时间: October 14, 2021 分类: C++ 评论 # Ch15 OOP ## 15.1 An Overview OOP is based on 3 fundamental concepts: 1. **Data abstraction**: Separate interface from implementation 2. **Inheritance**: Define classes that model the relationships among similar types. 3. **Dynamic binding**(run-time binding): Use objects(*virtual function*) while ignoring the details of thow they differ (through *pointers* or *references* to the base class). Inheritance: - A derived class must declare each inherited menber function it intends to override. - The access specifier in derivation list is *optional*, default value = `private` for `class`, `public` for `struct` - A derived class ctor initializes its *direct* base class only. - Base part and derived part in an object are not guranteed to be stored contiguosly. ## 15.3 Virtual Function Virtual function: - Root of an inheritance hierarchy almost define a virtual dtor `virtual ~dtor(){}`. - Any *nonstatic* member func (other than ctor) can be virtual - If a virtul func with default args is called, which version of args to use is denpent on the static type. Thus, such functions should use same default args. P607 - Virtual func declared in base class is implicitly virtual in derived classed: ```c++ // inside base class: virtual void func() {} // inside derived class: void func() = 0 // omitting keyword virtual is OK ``` --- ## 15.4 Abstract Base Classes - We can provide a definition for a *pure virtual* function (outside the class). It is used to provide some common operations. [c++ - Defining pure virtual functions outside the class definition - Stack Overflow](https://stackoverflow.com/questions/29449492/defining-pure-virtual-functions-outside-the-class-definition) ```c++ // outside the class void B::func() { /*common operations */} void B::~B() { /* some cleaning up *} ``` - Abstruct base class defines an *interface* - A derived class ctor initializes its *direct* base class only. --- ## 15.5 Access Control & Inheritance - Members and **friends** of a derived class can access this (derived) class's protected members. But the friends can't access the members of base class. - In fact, a derived type object has no special access to the protected *ordinary* base type object. ``` c++ class B { protected: int v; }; class D : public B { friend void func(D&); // can access D's protected member D::v friend void func(B&); // can't access B's protected member B::v void func(B& b){b.v=1;} // no direct access to ordinary object's v void func() {v=1;} // OK }; ``` ### Dervied-to-Base Conversion Accessibility depends on *who* is using the conversion and the *access specifier* in derivation. 1. The User Code: public 2. The Member func and Friend func of the derived class: `public`, `protected`, `private`==<-why private works== #what 3. The Member func and Friend func of the derived class of derived class: `public`, `protected` ```c++ class B { protected: int v = 1; }; class D :/*__what to fill_____*/ B { void member_func() { D d; // CASE#2: derived-to-base conversion in MEMBER FUNC & FRIENDS B b = (B)d; // OK: public, protected, private } friend void friend_func(); // CASE#2: same for the FRIENDS }; class AnotherClass : protected D { void func() { D d; // CASE#3: derived-to-base conversion in the Class derived from D B b = (B)d; // OK: public, protected (both for the D->B and AC->D inheritance) } }; int main() { D d; // CASE#1: derived-to-base conversion in USER CODE B b = (B)d; // OK: only public } ``` --- ## 15.6 Class Scope under Inheritance - Name Lookup happens before Type check. The base functions are hidden even if the functions in derived class have different paramete list. - Once override one of the (Base class's) overloaded functions, other overloaded functions will be hiden. Use `using` to bring all versions: https://stackoverflow.com/questions/888235/overriding-a-bases-overloaded-function-in-c ```c++ #include using namespace std; struct B { virtual void a(int) { cout << "B::a(int)" << endl;}; virtual void a(int, int) { cout << "B::a(int,int)" << endl;}; }; struct D: public B { void a(int) { cout << "D::a(int)" << endl;}; void a(int,int,int){ cout << "D::a(int,int,int)" << endl;};; using B::a; // bring all overloded function from B }; int main() { D d; int i = 0; d.a(i); // OK, D::a(int) // d.a(i, i); // NO matching function without `using` d.B::a(i,i); // OK, B::a(int,int) d.a(i, i, i); // OK, D::a(int,int,int) } ``` --- ## 15.7 Ctor and Copy Control - Use `using` to "inherit" ctors from a class's *direct* base class. Compiler generates ctors with a same parameter list as the ctor in the base class. - Unlike `using` ordinary members, this doesn't change the ctors access level and propertirs(explict, constexpr) - Base ctors with default parameters are split into serveral ctors withou default parameters #what - default copy, move ctors are not ingerited - a class that only contains inherited ctors will have a synthesized default ctor. -