首页 > 编程 > C++ > 正文

Boolan C++ 学习4 泛型编程 面向对象

2019-11-08 01:55:37
字体:
来源:转载
供稿:网友
Conversion functionnon-explicit one argument ctorPointer liker classes 智能指针,迭代器Function like classes Functor 仿函数namespaceclass template function templatespecialization, Partial spectializationtemplate template parameter 模板模板参数STLC++11 :Varadic template, auto, ranged-base for引用 refernce复合&继承关系下的构造与析构

Conversion function 转换函数

class Fraction{public: Fraction(int num, int den=1):m_num(num), m_den(den) { } Operator double() const { return (double) m_num/m_den ;}PRivate: int m_num, m_den;};Fraction f(3,4);double d = 4 + f;//调用operator double() 将f转换为double。

此处不写return type 由于已经指定double; 全局函数operator + (left + right) <–> left + right

non-explicit-one-argument ctor

class Fraction{public: Fraction (int num, int den = 1): m_num(num), m_den(den) { }Fraction operator+ (const Fraction& f) { return Fraction (...);} private: int m_num, m_den;};Fraction f(3, 5);Fraction d2 = f + 4;//调用non-explicit ctor 将4转为Fraction(4,1)然后调用operator +

注意此处与conversion function区别 如果定义d2 为double 类型与上面相同则无法转换。 注意 operator + (单参数) <–> f + 4; 左 + 右 无法 调用 4 + f;

如果同时定义转换函数和单参数non-explicit 构造函数将会造成错误编译器无法选择。 如果构造函数前面加上explicit 关键字 构造函数无法自动转化4 为 Fraction 类型 此处也会产生错误。 STL中conversion函数的应用

template <class Alloc>class vector<bool,Alloc>{public:typedef __bit_reference refernce;protected:refernce operator[](size_type n) { return *(begin() + difference_type(n));}}...struct __bit_refernce { unsigned int*p; unsigned int mask;public: operator bool() const { return !(!(*p & mask));}}

此处reference 可以自动转换为bool 类型 。

Pointer-like classes

1.智能指针

template<class T>class shared_ptr{public: T& operator*() const {return *px;} T* operator->() const {return px;} shared_ptr(T* p):px(p) {}private: T* px; long* pn;...};struct Foo{ method() {}};shared_ptr<Foo> sp(new Foo);Foo f(*sp);sp->method(); --> px->method

即必须重载 类内操作符 operator * 和operator-> 注意此处-> 符号并不会消耗。 STL boost unique_ptr scoped_ptr 独占指针对象,并保证指针所指对象生命周期与其一致 shared_ptr shared_ptr 可共享指针对象,可以赋值给shared_ptr或weak_ptr。 指针所指对象在所有的相关联的shared_ptr生命周期结束时结束,是强引用。 weak_ptr weak_ptr 它不能决定所指对象的生命周期,引用所指对象时,需要lock()成shared_ptr才能使用。 参考:http://blog.csdn.net/xt_xiaotian/article/details/5714477 https://my.oschina.net/hevakelcj/blog/465978 2. 迭代器

template<class T>struct __list_node { void* prev; void* next; T data;};template<class T, class Ref, class Ptr>struct __list_iterator { typedef __list_iterator <T, Ref, Ptr> self; typedef Ptr Pointer; typedef Ref refernce; typedef __list_node<T>* link_type; link_type node; bool operator==(const self& x) const {return node == x.node;} bool operator != (const self& x) const {return node !=x.node;} refernce operator*() const {return (*node).data;} pointer operator->() const {return &(operator*());} self& operator++() {node = (link_type) (*node).next;return *this;} self& operator++(int) {self tmp = *this; ++*this;return tmp;}self& operator--() {node = (link_type)((*node).prev); return *this;}self operator--() {self tmp = *this;--*this; return tmp;}} (1)前置++运算符的重载方式: 成员函数的重载: 函数类型& operator++() 友元函数的重载:friend 函数类型& operator++(类类型& ) (2)后置++运算符的重载方式: 成员函数的重载:函数类型& operator++(int) 友元函数的重载:friend 函数类型& operator++(类类型&, int)

1、输入迭代器:只读,一次传递 为输入迭代器预定义实现只有istream_iterator和istreambuf_iterator,用于从一个输入流istream中读取。一个输入迭代器仅能对它所选择的每个元素进行一次解析,它们只能向前移动。一个专门的构造函数定义了超越末尾的值。总是,输入迭代器可以对读操作的结果进行解析(对每个值仅解析一次),然后向前移动。 2、输出迭代器:只写,一次传递 这是对输入迭代器的补充,不过是写操作而不是读操作。为输出迭代器的预定义实现只有ostream_iterator和ostreambuf_iterator,用于向一个输出流ostream写数据,还有一个一般较少使用的raw_storage_iterator。他们只能对每个写出的值进行一次解析,并且只能向前移动。对于输出迭代器来说,没有使用超越末尾的值来结束的概念。总之,输出迭代器可以对写操作的值进行解析(对每一个值仅解析一次),然后向前移动。 3、前向迭代器:多次读/写 前向迭代器包含了输入和输出迭代器两者的功能,加上还可以多次解析一个迭代器指定的位置,因此可以对一个值进行多次读/写。顾名思义,前向迭代器只能向前移动。没有为前向迭代器预定义迭代器。 4、双向迭代器:operator– 双向迭代器具有前向迭代器的全部功能。另外它还可以利用自减操作符operator–向后一次移动一个位置。由list容器中返回的迭代器都是双向的。 5、随机访问迭代器:类似于一个指针 随机访问迭代器具有双向迭代器的所有功能,再加上一个指针所有的功能(一个指针就是一个随机访问迭代器),除了没有一种“空(null)”迭代器和空指针对应。基本上可以这样说,一个随机访问迭代器就像一个指针那样可以进行任何操作,包括使用操作符operator[]进行索引,加某个数值到一个指针就可以向前或者向后移动若干个位置,或者使用比较运算符在迭代器之间进行比较。 参考:http://www.tuicool.com/articles/ZJ36Rf http://blog.csdn.net/shawvichan/article/details/17639763 http://www.cnblogs.com/yc_sunniwell/archive/2010/06/25/1764934.html

Function-like classes

仿函数 functor

template <class T>struct identity {const T&operator()(const T& x) const {return x;}};template<class Pair>struct select1st {const typename Pair::first_type&operator() (const Pair& x) const {return x.first}};template <class Pair>struct select2nd {const typename Pair::second_type& operator()(const Pair& x) const {return x.second; }};template <class Arg,class Result>struct unary_function {typedef Arg argument_type;typedef Result result_type;};template <class Arg1, classArg2, class result>struct binary_function { typedef Arg1 first_argument_type; typedef Arg2 second_argument_type; typedef Result result_type;};

重载operator() 实现类似函数调用方式。参考python。

参考:http://blog.csdn.net/cracker_zhou/article/details/51627811 http://blog.csdn.net/tianshuai1111/article/details/7687983 http://blog.csdn.net/Robin__Chou/article/details/49329985

namespace

#include <iostream>#include <memory>//shared_ptrusing namespace std;namespace jj01{void test_member_template(){}}//namespace//-------------#include <iostream>#include <list>namespace jj02{template<typename T>using Lst = list<T, alloctor<T>>void test_template_param(){...}}//namespace//-------------int main(int argc,char** argv){jj01::test_memeber();jj02::test_template_param();}

class template, function template, member template

1.class template

template<tyoename T>class complex{public: complex (T r = 0, T i = 0): re (r), im(i) {} complex& operator+= (const complex&); T real() const {return re;} T imag() const {return im;}private: T re,im; };{ complex<double> c1(1.5, 2.5); compex<int> c2(2, 6);}function templatetemplate<class T>inline const T&min (const T& a, const T& b) { return b<a?b:a;}class stone{public: stone(int w, int h, int we): _w(w), _h(h), _we(we) {} bool operator < (const stone& rhs) const {return _we < rhs._we;}private: int _w, _h, _we;};stone r1(2,3), r2(2,3),r3;r3 = min(r1, r2);

此处编译器会对函数模板进行推导 推导的结果是T类型为stone 调用stone:: operator <. 3. member template 成员模板

template <class T1, class T2>struct pair { typedef T1 first_type; typedef T2 second_type; T1 first; T2 second; pair():fist(T1()), second(T2()) {} pair(const T1& a, const T2& b): fist(a), second(b) {} template<class U1, clas U2> pair(const pair<U1, U2>& p):first(p.first), second(p.second) {}}//可以用于继承类中class Base1{};class Derived1:public Base1 {};class Base2{};clss Dedived2:publlic Base2 {};pair<Derived1,Deived2> p;pair<Base1, Base2> p2(p);pair<Base1, Base2> p2(pair<Derived1, Derived2>());//Derived1是Base1, Derived2是Base2,所以可以。//example 2template <typename _Tp>class shred_ptr:public __shared_ptr<_Tp>{... template<typename _Tp1> explicit shared_ptr(_Tp1* __p):__shared_ptr<_Tp>(__p){}};Base1* ptr = new Derived1;//up-castshared_ptr<Base1> sptr(new Derived);//模拟up-cast

如果要在外面定义成员模板,必须包含两个模板形参表,类模板形参和自己的模板形参。首先是类模板形参表,然后是自己的模板形参表。 类似: template<class T, class Alloc> template <class I> void MyVector<T, Alloc>::assign(I first, I last) { cout<<"assign"<<endl; }

参考:http://blog.csdn.net/wuzhekai1985/article/details/6654034

specialization, 模板特化

template <class Key>struct hash {};template<>struct hash<char> { size_t operator()(char x) const {return x;}};template<>struct hash<int> { size_t operator()(int x) const {return x;}};template <>struct hash<long> { size_t operator()(long x) const {return x;}};patial specialization, 模板偏特化 – 个数偏template <typename T, typename Alloc = ...>class vector{...};template<typename Alloc = ...>class vector<bool, Alloc>{...};//bool 绑定 T范围偏template <typename T>class C{...};template <typename T>classC<T*>{...};c<string> obj1;c<string*> obj2;

函数没有偏特化只有全特化。 参考: http://www.jb51.net/article/56004.htm http://blog.csdn.net/thefutureisour/article/details/7964682/ http://blog.csdn.net/gatieme/article/details/50953564

template template parameter 模板模板参数

template <typename T, template <typename T> class Container>calss XCls{private: Container<T> c;public:...};template <typename T>using Lst = list<allocator<T>>;XCls<string, list> mylst1;//wrongXCls<string, Lst> mylst2;//correct//----------template <typename T, template <typename T> class SmartPtr>class XCls{private: SmartPtr<T> sp;public: XCls(): sp(new T) {}}XCls<string, shared_ptr> p1;XCls<double, unique_ptr> p2;//wrongXCls<int, weak_ptr> p3;//wrongXCls<long, auto_ptr> p4;//----以下不是template template parametertemplate <class T, class Sequnce = deque<T>>class stack { friend bool operator == <> (const stack&, const stack&); friend bool operatir < <> (const stack&, const stack&);protected: Sequence c;//底层容器};stack<int> s1;stack<int, list<int>> s2;

模板模板参数就是将一个模板作为另一个模板的参数。 所以最后一个例子不是。 另外还有无类型模板 : template

STL

容器,迭代器, 算法, 仿函数,待补充。

C++ 11 补充

Variadic template 数量不定模板参数void print (){}template <typename T, typename... Types>void print (const T& firstArg, const Types&...args){ cout << firstArg<<endl; print(args...)}

此处用于tempalte paramters 就是template parameters pack (模板参数包) 个数可以用sizeof…(args) 来获得。最后sizeof…(args) = 0 时调用第一个重载的空print函数什么都不做返回。

参考:http://www.cnblogs.com/tekkaman/p/3501122.html http://blog.csdn.net/wag2765/article/details/50581469 2. auto C++引入auto关键字主要有两种用途:一是在变量声明时根据初始化表达式自动推断该变量的类型,二是在声明函数时作为函数返回值的占位符。

list<string> c;list<string>::iterator ite;ite= find(c.begine(),c.end9),target);//可以用auto 代替auto = find(...)//但是不能写为auto ite;ite = find(...)//此时编译器无法推断auto类型。//作为函数返回值占位符时,auto主要与decltype关键字配合使用,作为返回值类型后置时的占位符。此时,关键字不表示自动类型检测,仅仅是表示后置返回值的语法的一部分。template<class T, class U>auto add(T t, U u) -> decltype(t + u) { return t + u;}

参考:http://blog.csdn.net/Xiejingfa/article/details/50469045 http://www.2cto.com/kf/201404/293503.html 3.Range-base for

for (decl:coll){}for (int i : {1,2,3}){ cout << i << endl;}vector<double> vec;for (auto elem :vec) { cout << elem << endl;//按值传递}for (auto& elem: vec) { elem* = 3;//按引用传递可以改变包内内容}

Reference引用

1.引用不能重新赋值 2. 引用不能单独声明 3. object 和其引用大小地址均相同 4. 引用不构成重载。 const 函数构成重载即func() const {} 构成重载由于其是函数签名的一部分。 5. sizeof(值) = sizeof(引用)

复合与继承关系下的构造与析构

构造由内而外 析构相反由外而内 构造先base 再component 最后自己。 Derived::Derived():Base():COmponent(){} 析构先自己再component最后base Derived::~Derived(){…~Component,~Base()}


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选