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 Luchao { 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); Luchao::pair<int,double> l(9,9.8); std ::cout << a; std ::cout << l; std ::cout << "---" << std ::endl ; Luchao::identity<Luchao::pair <int ,double >> lcidentity; Luchao::identity<std ::pair <int ,double >> stdidentity; std ::cout << lcidentity(l); std ::cout << stdidentity(a); int first = Luchao::select1st<std ::pair <int ,double >>()(a); double second = Luchao::select2nd<Luchao::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 Luchao { 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 () { Luchao::pair<int,int> a(1,2); Luchao::pair<int,double> b(1,9.9); Luchao::pair<int,double> c(b); Luchao::func<int ,int >(a); Luchao::func(a); Luchao::func(c); Luchao::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 Luchao { 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 << Luchao::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 Luchao { 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 () { Luchao::Tmp<int ,std ::string > t1; Luchao::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 Luchao { 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 () { Luchao::vector <std ::string > t (std ::string ("llc" )) ; std ::cout << t.get() << std ::endl ; std ::string *str = new std ::string ("abc" ); Luchao::vector <std ::string *> t1 (str) ; std ::cout << t1.get() << std ::endl ; delete str; return 0 ; }
看了前11集没看了,然后去看effective 和insight class model,现在接着看.