c++面对对象下(0-10)笔记 类的分类
不带pointer的类
带Pointer的类: 那么 1)拷贝构造,2)拷贝赋值运算符, 3)析构函数,这3个重点函数手写,不要使用编译器默认生成的.(因为涉及到 深浅拷贝问题)
类的使用 (重载运算符)
像指针的类
像函数的类
类和类的关系
继承(Inheritance)
复合(Composition)
委托(Delegation)
1.conversion function(转换函数)
首先编译器找全局的+运算符是否重载.
然后找类是否能类型转换
在+和<<运算符作用时,Fraction类都转化为double类型了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 #include <iostream> class Fraction { public : Fraction (int num,int den=1 ) :m_numerator (num),m_denominator (den) {} operator double () const ; private : int m_numerator; int m_denominator; };Fraction::operator double () const { return ((double )m_numerator/m_denominator); }int main () { Fraction a (1 ,2 ) ; double ans = 1.2 + a; std::cout << "a=" << a << " ans=" << ans; return 0 ; }
2. non-explicit-one-argument-constructer
=> implicit-one-argument-constructor
接收一个实参的隐式构造函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 #include <iostream> class Fraction { public : Fraction (int num,int den=1 ) :m_numerator (num),m_denominator (den) {} Fraction operator +(const Fraction &)const ; private : int m_numerator; int m_denominator; friend std::ostream& operator <<(std::ostream&,const Fraction&); }; Fraction Fraction::operator +(const Fraction &r)const { return Fraction (m_numerator+r.m_numerator,m_denominator+r.m_denominator); } std::ostream&operator << (std::ostream& os,const Fraction &r) { return os << (double )r.m_numerator/r.m_denominator << std::endl; }int main () { Fraction a (1 ,2 ) ; std::cout << a+1 <<std::endl; return 0 ; }
歧义1: conversion function Vs. non-explicit-one-argument-constructor 学习到operator double() {}这种写法是定义类对象的类型转换.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 #include <iostream> class Fraction { public : Fraction (int num,int den=1 ) :m_numerator (num),m_denominator (den) {} operator double () const ; Fraction operator +(const Fraction &)const ; private : int m_numerator; int m_denominator; friend std::ostream& operator <<(std::ostream&,const Fraction&); }; Fraction Fraction::operator +(const Fraction &r)const { return Fraction (m_numerator+r.m_numerator,m_denominator+r.m_denominator); } std::ostream&operator << (std::ostream& os,const Fraction &r) { return os << (double )r.m_numerator/r.m_denominator << std::endl; }Fraction::operator double () const { return (double )m_numerator / m_denominator; }int main () { Fraction a (1 ,2 ) ; std::cout << a+1 <<std::endl; return 0 ; }
可以看到这里有二义性.a可以执行类型转换,且1可以进行隐式构造.
解决:构造函数explicit,明确化,不允许隐式类型转换.
3.pointer-like classes 像指针的类
主要是需要重载类的2个运算符
*:返回的T&,也就是指向对象的本身(引用)
->:返回的是指针,将类自己的指针成员暴露出来
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 #include <iostream> template <typename T>class shared_ptr { public : T& operator *()const ; T* operator ->()const ; private : T* px; long *pn; };template <typename T> T& shared_ptr<T>::operator *()const { return *px; }template <typename T> T* shared_ptr<T>::operator ->()const { return px; }int main () { return 0 ; }
4.function-like-classes 像函数的类
主要是重载()运算符,operator()(),然后下面是随便写的一段测试小代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 #include <iostream> namespace Emerald { template <typename T1,typename T2> struct pair { typedef T1 first_type; typedef T2 second_type; T1 first; T2 second; pair ():first (T1 ()),second (T2 ()) {} pair (const T1& a,const T2& b):first (a),second (b) {} friend std::ostream& operator <<(std::ostream&,const pair<int ,double >&); }; template <typename T> struct identity { const T& operator () (const T&) const ; int operator () () const ; }; template <typename T> const T& identity<T>::operator ()(const T& x)const { return x; } template <typename T> int identity<T>::operator ()()const { std::cout << "identity()" << std::endl; return 1 ; } template <typename Pair> struct select1st { const typename Pair::first_type& operator () (const Pair&) const ; }; template <typename Pair> const typename Pair::first_type& select1st<Pair>::operator ()(const Pair&r)const { return r.first; } template <typename Pair> struct select2nd { const typename Pair::second_type& operator () (const Pair&) const ; }; template <typename Pair> const typename Pair::second_type& select2nd<Pair>::operator ()(const Pair& r)const { return r.second; } std::ostream& operator << (std::ostream& os,const pair<int ,double >& r) { return os << "(" <<r.first << "," << r.second << ")" << std::endl; } } std::ostream& operator <<(std::ostream& os,const std::pair<int ,double >& r) { return os << "(" << r.first << "," << r.second << ")" << std::endl; }int main () { std::pair<int ,double > a (1 ,2.3 ) ; Emerald::pair<int ,double > l (9 ,9.8 ) ; std::cout << a; std::cout << l; std::cout << "---" << std::endl; Emerald::identity<Emerald::pair<int ,double >> lcidentity; Emerald::identity<std::pair<int ,double >> stdidentity; std::cout << lcidentity (l); std::cout << stdidentity (a); int first = Emerald::select1st<std::pair<int ,double >>()(a); double second = Emerald::select2nd<Emerald::pair<int ,double >>()(l); std::cout << first << std::endl; std::cout << second << std::endl; return 0 ; }
5.namespace 模板的分类 6.class template(类模板) 7.function template(函数模板)
函数接收的参数支持多种类型.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 #include <iostream> template <typename T>inline const T&min (const T& a,const T& b) { return a < b ? a : b; }class stone { public : stone () = default ; stone (int w,int h,int we = 0 ) :_w(w),_h(h),_weight(we) {} bool operator < (const stone&)const ; private : int _w,_h,_weight; friend std::ostream& operator << (std::ostream&,const stone&); };bool stone::operator <(const stone& r)const { return _weight < r._weight; } std::ostream& operator << (std::ostream& os,const stone &r) { return os << "(" << r._w << " " << r._h << " " << r._weight << ")" << std::endl; }int main () { stone r1 (2 ,3 ,1 ) ,r2 (3 ,3 ,4 ) ,r3 ; r3 = min (r1,r2); std::cout << r3; return 0 ; }
模板函数调用,既可以手动指出参数类型,也可以不指出
下面是function template(函数模板) vs. function-like template class(像函数的模板类),实现相同的功能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 #include <iostream> namespace Emerald { template <typename T1,typename T2> struct pair { typedef T1 first_type; typedef T2 second_type; T1 first; T2 second; pair ():first (T1 ()),second (T2 ()) {} pair (const T1& a,const T2& b):first (a),second (b) {} }; template <typename T1,typename T2> void func (const pair<T1,T2> &r) { std::cout << "(" << r.first << " " << r.second << ")" << std::endl; } template <typename T1,typename T2> class Func { public : void operator () (const pair<T1,T2>&) const ; }; template <typename T1,typename T2> void Func<T1,T2>::operator ()(const pair<T1,T2>& r)const { std::cout << "(" << r.first << " " << r.second << ")" << std::endl; } }int main () { Emerald::pair<int ,int > a (1 ,2 ) ; Emerald::pair<int ,double > b (1 ,9.9 ) ; Emerald::pair<int ,double > c (b) ; Emerald::func <int ,int >(a); Emerald::func (a); Emerald::func (c); Emerald::Func <int ,double >()(c); return 0 ; }
8.member template(成员模板)
在一个模板类中,使用成员模板函数作为其构造函数,可以接收其它类型的变量(例如类的成员变量是基类,但传入的是父类变量来构造)作为构造参数.
如shared_ptr的实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 #include <iostream> namespace llc { class Base1 {}; class Base2 {}; class Derived1 :public Base1 {}; class Derived2 :public Base2 {}; template <typename T1,typename T2> struct pair { typedef T1 first_type; typedef T2 second_type; T1 first; T2 second; pair ():first (T1 ()),second (T2 ()) {} pair (const T1& a,const T2& b):first (a),second (b) {} template <typename U1,typename U2> pair (const llc::pair<U1,U2>& p) : first(p.first),second(p.second) { } }; }template <typename T1,typename T2>void func (llc::pair<T1,T2>& r) { std::cout << "(" << r.first << " " << r.second << ")" << std::endl; }template <typename T1,typename T2>class Func { public : void operator () (const llc::pair<T1,T2>& r) const { std::cout << "(" << r.first << " " << r.second << ")" << std::endl; } };int main () { { llc::pair<int ,int > a (1 ,2 ) ; llc::pair<int ,double > b (1 ,9.9 ) ; llc::pair<int ,int > c (b) ; func <int ,int >(a); func (b); Func <int ,int >()(c); Func <int ,double >()(b); } llc::pair<llc::Derived1,llc::Derived2> b; llc::pair<llc::Base1,llc::Base2> a (b) ; return 0 ; }
9. specialization,模板特化 泛化(也就是普通的模板):
对于特殊的类型想要特殊处理,就将此类型的类单独拿出来写一遍,叫做特化
注意,有泛化(也就是有模板类)才有特化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 #include <iostream> namespace Emerald { template <typename T> struct hash { hash ()=default ; }; template <> struct hash <long > { long operator () (long x) const {return x;} }; template <> struct hash <int > { int operator () (int x) const {return x*2 ;} }; template <> struct hash <char > { char operator () (char c) const {return c;} }; }int main () { std::cout << Emerald::hash <int >()(100 ); return 0 ; }
10. 模板偏特化 (partial specialization) 1. 参数个数偏特化(从左到右,根据需要特化)
例子不是很恰当
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 #include <iostream> namespace Emerald { template <typename T1,typename T2> class Tmp { public : Tmp ()=default ; Tmp (const T1& a,const T2& b):a (a),b (b){}; void printf () const {std::cout << "base" << std::endl;} private : T1 a; T2 b; }; template <typename T2> class Tmp <bool ,T2> { public : Tmp ()=default ; Tmp (const T2& b):flag (true ),b (b){} void printf () const {std::cout<< "partial specialization" << std::endl;} private : bool flag; T2 b; }; }int main () { Emerald::Tmp<int ,std::string> t1; Emerald::Tmp<bool ,std::string> t3; t1.printf (); t3.printf (); return 0 ; }
2. 范围上的偏特化
如:本来接受任意类型T,可以通过特化将类型缩小到指针,(指针本身是一种类型)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 #include <iostream> namespace Emerald { template <typename T> class vector { public : vector ():data (){} vector (const T& r):data (r){} const T& get () const {return data;} int printf () const {return data.length ();}; private : T data; }; template <typename T> class vector <T*> { public : vector ():data (nullptr ){} vector (T* p):data (p){} vector (const T* p):data (p){} const T& get () const { return *data;} private : T *data; }; }int main () { Emerald::vector<std::string> t (std::string("llc" )) ; std::cout << t.get () << std::endl; std::string *str = new std::string ("abc" ); Emerald::vector<std::string*> t1 (str) ; std::cout << t1.get () << std::endl; delete str; return 0 ; }
看了前11集没看了,然后去看effective 和insight class model,现在接着看.