C++面向对象设计基础

一般类、&、const、模板、友元函数、操作符重载基本用法及实现

complex.h

#ifndef COMPLEX_H
#define COMPLEX_H
#include<ostream>
using namespace std;

template<typename T>
class Complex{
	public:
		Complex():re(0),img(0){
			
		}
		// 为什么构造函数不能传引用?
		// 原因:不能给引用形式传递临时变量
		//Complex<double> b(1.5, 2.0);改为以下两行即可传引用 
		//double x=1.5,y=2.0;             
		//Complex<double> b(x, y); 
		Complex(T _re,T _img):re(_re),img(_img){
			
		}
		//传引用,但存在修改,函数不能用const
		void setRe(const T& _re){
			re=_re;
		}
		void setImg(const T& _img){
			img=_img;
		}
		//不能返回引用,返回引用代表可能修改,与const矛盾
		T getRe() const {
			return re;
		}
		T getImg() const{
			return img;
		}
		
		//调用类,必须要加上模板参数
		inline Complex<T>& operator+(const Complex<T>& a);
		
		//友元函数或者友元类可以访问类的私有变量
    	//类内部使用友元函数模板,必须加上typename
		template<typename N>
		inline friend Complex<N> operator+(const Complex<N>& a,const N& b);	
		
		template<typename N>
		inline friend Complex<N> operator+(const N& a,const Complex<N>& b);	
		
	private:
		T re;
		T img;
};

//在类外实现模板类的成员函数时应该在成员函数之前加上关键字template
//成员函数前必须加上和类模板一样的声名template<typename T>,
//而且类的名称要写为Complex<T>。当在类外实现成员函数时,<T>不能省略。 
template<typename T>
inline Complex<T>& Complex<T>::operator+(const Complex<T>& a){
	this->re=this->re+a.re;
	this->img=this->img+a.img;
	return *this;
}

template<typename T>
inline Complex<T> operator+(const Complex<T>& a,const T& b){
	Complex<T> sum=Complex<T>(a.re+b,a.img);
	return sum;
}

template<typename T>
inline Complex<T> operator+(const T& a,const Complex<T>& b){
	Complex<T> sum= Complex<T>(a+b.re,b.img);
	return sum;
}

// 重载的是ostream,必须有返回值,满足连续打印的情况。
template<typename T>
inline ostream& operator<<(ostream& os,const Complex<T>& a){
	return os<<a.getRe()<<"---"<<a.getImg();
}

#endif  

complexTest.cpp

#include<iostream>
#include "complex.h"
using namespace std;
int main()
{
    Complex<double> a;
    a.setRe(2.0);
    a.setImg(3.0);
    cout << a << endl;
    Complex<double> b(1.5, 2.0);
    a = a + 3.0;
    cout << a << endl;
    Complex<double> c = a + b;
    cout << c << endl;
    Complex<double> d = 3.0 + b;
    cout << d << endl;
    cout << c<< endl << d;
    return 0;
}

含有指针的类,构造,拷贝构造,赋值,析构函数

myString.h

#ifndef MYSTRING_H
#define MYSTRING_H
#include<ostream>
#include<string.h>
using namespace std;
class myString{
	public:
		myString(const char* _str=0){
			//为什么这里必须判空,拷贝构造函数就不用? 
			if(_str==0){
				str=new char[1];
				strcpy(str,"\0");
			}else{
				str=new char[strlen(_str)+1];
				strcpy(str,_str);
			}
		}
		
		// 拷贝构造函数必须使用引用,否则会无限循环
		myString(const myString& _str){
			str=new char[strlen(_str.str)+1];
			strcpy(str,_str.str);
		}
		
		myString& operator=(const myString& _str){
			if(str==_str.str){
				return *this;
			}else{
				delete []str;
				str=new char[strlen(_str.str+1)];
				strcpy(str,_str.str);
				return *this;
			}
		}
		
		// 必须要有析构
		~myString(){
			delete []str; 
		}
		
		char* getStr() const{
			return str;
		}
		
		friend ostream& operator<<(ostream& os,myString& _str);
	private:
		char* str;
};

//ostream& operator<<(ostream& os,myString _str){
//	return os<<_str.getStr();
//}

// 友元函数类外实现
ostream& operator<<(ostream& os,myString& _str){
	return os<<_str.str;
}

#endif

myStringTest.cpp

#include<iostream>
#include"myString.h"
using namespace std;
int main()
{
    myString a("defg");
    myString b;
    b = a; //调用的赋值函数
    myString c = a; // 调用的拷贝构造函数
    cout << a << "*" << b << "*" << c << "*" << endl;

    return 0;
}

类型转换函数、explicit用法

fraction.h

#ifndef FRACTION_H
#define FRACTION_H

class Fraction{
	public:
		//explicit不让构造函数发生自动转换
		//避免 operator double() const 与构造函数都可以类型转换发生二义性 
		explicit Fraction(int _numerator,int _denominator=1):numerator(_numerator),denominator(_denominator){
			
		}
		//在需要转换成double时自动调用 
		operator double() const{
			return (double)numerator/denominator;
		}
		Fraction& operator+(const Fraction& a){
			this->numerator = this->numerator*a.denominator + this->denominator+a.numerator;
        	this->denominator = this->denominator * a.denominator;
			return *this;
		}
	private:
		int numerator;
		int denominator;
};

#endif

fractionTest.cpp

#include<iostream>
#include"fraction.h"
using namespace std;
int main(){
    Fraction a(1, 4);
    cout << (double)a << endl;
    cout << a + 4;
    return 0;
}

将函数作为另一个函数参数两种方式:1)函数指针;2)仿函数

bigger.h

#ifndef BIGGER_H
#define BIGGER_H

class BiggerThan{
	public:
		BiggerThan(double _x):x(_x){
			
		}
		bool operator()(const double& i) const {
			return i>x;
		}
	private:
		double x;
};

#endif

functor.cpp

#include<iostream>
#include "bigger.h"
using namespace std;
// 仿函数
int biggerNumber(double* arr, int size, const BiggerThan& bigger){
	int cnt=0;
	for(int i=0;i<size;i++){
		bigger(arr[i])?cnt++:cnt;
	}
	return cnt;
}


// 函数指针
int biggerNumberPoint(double* arr, int size, double cpy, bool (*fp)(double,double)){
	int cnt=0;
	for(int i=0;i<size;i++){
		fp(arr[i],cpy)?cnt++:cnt;
	}
	return cnt;
}
bool biggerPoint(double i,double x){
	return i>x;
}



int main()
{
    BiggerThan bigger(10);
    double array[] = {1.4, 12.0, 14.0, 15.0, 3.0};
    cout << biggerNumber(array, 5, bigger) << endl;
    cout << biggerNumberPoint(array, 5, 10, biggerPoint) << endl;
    return 0;
};

智能指针

  • 智能指针可以自动释放占用的内存
  • shared_ptr 共享智能指针
  • unique_ptr独享智能指针,跟普通指针大小一样,不允许拷贝构造
  • weak_ptr共享指针指针,解决循环引用问题,从智能指针生成

pointer.h

#ifndef SMART_POINTER_POINTER_H
#define SMART_POINTER_POINTER_H
#include<memory>
#include<string>
#include<vector>
#include<iostream>
using namespace std;
class StringBlob{
public:
    StringBlob()  {}
    StringBlob(initializer_list<string> ss) : sp(make_shared<vector<string>>(ss)) {}
    void push_back(const string& s) {
        sp->push_back(s);
    }
    void pop_back(){
        if(check(0))
            sp->pop_back();
    }

private:
    shared_ptr<vector<string> > sp;
    bool check(const int& i){
        if(i>0 && i<sp->size())
            return true;
        else
            return false;
    }

};
class WoMan;
class Man{
public:
    //注意使用智能指针进行值传递时的内存泄露问题
    void setdata(shared_ptr<WoMan> _mdata){
        mdata = _mdata;
    }
    // 注意程序结束时析构函数是否会被调用,来判断是否存在内存泄漏问题
    ~Man(){
        std::cout << "Man has destory" << std::endl;
    }
private:
//    shared_ptr<WoMan> mdata;
    weak_ptr<WoMan> mdata;
};

class WoMan{
public:
    void setdata(shared_ptr<Man> _mdata){
//        std::cout << _mdata.use_count() << "......." << endl;
        mdata = _mdata;
//        std::cout << _mdata.use_count() << "......." << endl;
    }
    ~WoMan(){
        std::cout << "woman has destory" << std::endl;
    };
private:
    shared_ptr<Man> mdata;
};
#endif //SMART_POINTER_POINTER_H

pointerTest.cpp

#include<iostream>
#include"pointer.h"
#include<string>
#include<iostream>
using namespace std;
int main()
{
    StringBlob s1 = {"test1", "tess4", "test5"};
    s1.push_back("test");
    // unique_ptr<string> up = new string("wuhjandaxue"); wrong explicit不允许拷贝构造

    //unique_ptr独享对象,一些基本用法
    unique_ptr<string> up(new string("wuhand"));
    unique_ptr<string> up3(new string("beijing"));
    string* up_point = new string("11111");
    cout << "unique_ptr size " << sizeof(up) << endl;
    cout << *up << endl;
    unique_ptr<string> up2(up.release()); // 所有权转移
    cout << *up2 << endl;
    cout <<  *up3 << endl;
    up3.reset(up_point); // 所有权转移
    cout << *up3 << endl;
    up3.reset(nullptr);

    // weak_ptr共享指针的复制指针,可以避免共享指针的循环引用问题
    shared_ptr<WoMan> woman = make_shared<WoMan>();
    shared_ptr<Man> man = make_shared<Man>();
    woman->setdata(man);
    man->setdata(woman);
    cout << man.use_count() << endl; // 2
    cout << woman.use_count() << endl; // 1
    cout << "............" << endl;

    //weak_ptr基本用法
    auto p = make_shared<int>(3);
    weak_ptr<int> w_p(p);
    cout << "wark ptr size " << sizeof(w_p) << endl;
    //返回指向w智能指针,或者空
    auto p2 = w_p.lock();
    cout << p.use_count() << endl;
    weak_ptr<int> w_p2(p);
    p2.reset();
    p.reset();
    // 判断p.use_count是否为0
    if(w_p2.expired()){
        cout << "p has no object" << endl;
    }
    cout << p.use_count() << endl;
    return 0;
}

可变参数、auto、Ranged-base

sample_c11.cpp

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
void print()
{

}
// 1. 可变参数
template<typename T, typename... Types>
void print(const T& first, const Types&... args)
{
    cout << first << endl;
    print(args...);
}

int  main()
{
    print("wuhan", "beijing", 2333333);
    vector<int> test = {1, 50, 3, 5, 4};
    // vector<int>::iterator position = find(test.begin(), test.end(), 50);
    // 2. auto可以替代上面参数
    auto position =find(test.begin(), test.end(), 50);
    if(position != test.end()){
        cout << *position << endl;
        cout << "position " << distance(test.begin(), position) << endl;
    }
    // 3. ranged-base
    // 值访问
    for(auto i : test){
        cout << i << " ";
    }
    cout << endl;
    // 引用访问
    for(auto &i : test){
        i = 10;
    }
    for(auto i : test){
        cout << i << " ";
    }
    cout << endl;
    return 0;
}

继承和多态,虚函数、打破虚函数

quote.h

#ifndef QUOTE_H
#define QUOTE_H

#include<iostream>
using namespace std;
class Quote{
	public:
		Quote(double _price):price(_price){
			
		}
		virtual const double sell_price() const{
			return price;
		}
		// 基类往往需要构造一个虚析构函数
		virtual ~Quote(){
			cout<<"Quote has destroy"<<endl;
		}
	protected:
		double price;	
};

class Bulk_Quote:public Quote{
	public:
		Bulk_Quote(double _radio,double _price):radio(_radio),Quote(_price){
			
		}
		virtual const double sell_price() const{
			return price*radio;
		}
		virtual ~Bulk_Quote(){
			cout<<"Bulk_Quoto has destroy"<<endl;
		}
	private:
		double radio;
};

#endif

quoteTest.cpp

#include<iostream>
#include "quote.h"
#include<memory>
using namespace std;
int main()
{

	Quote q1=Quote(10);
	Bulk_Quote q2=Bulk_Quote(0.5, 10);
    cout << q1.sell_price() << endl;
    cout << q2.sell_price() << endl;
    // 强制访问基类函数
    cout << q2.Quote::sell_price() << endl;

//    智能指针方式调用 
//    unique_ptr<Quote> q1(new Quote(10));
//    unique_ptr<Quote> q2(new Bulk_Quote(0.5, 10));
//    // 多态条件:1)指针/引用 2)派生类到基类 3) 虚函数
//    cout << q1->sell_price() << endl;
//    cout << q2->sell_price() << endl;
//    // 强制访问基类函数
//    cout << q2->Quote::sell_price() << endl;
    return 0;
}

容器vector, list等、关联容器map, set等

stl_test.cpp

#include<iostream>
// 算法
#include<algorithm>
// 仿函数
#include<functional>
#include<vector>
#include<list>
#include<deque>
#include<set>
#include<map>
#include<unordered_set>
using namespace std;
int main()
{
    /*第一类容器..............*/
    cout << "..........vector............" << endl<<endl;
    vector<int> a = {1, 4, 3, 7, 10};
    a.push_back(8);
    cout << "vector size " << a.size() << endl;
    // vector capactity是以接近2^n进行容量增大的
    cout << "vector capacity " << a.capacity() << endl;
    // greater<int>()仿函数,本质是个模板,()创建了一个临时对象
    sort(a.begin(), a.end(), greater<int>());
    for(int temp : a)
    {
        cout << temp << " " ;
    }
    cout<<endl;
    auto target = find(a.begin(), a.end(), 4);
    if(target != a.end())
        cout << "find target postion " << distance(a.begin(), target) << endl;
	cout << "..........list, foward_list............" << endl<<endl;
    //list, foward_list 地址不连续,不存在[]
    list<int> a_list = {7, 5, 2, 1, 6, 8};
    // 列表中自带了sort函数
    a_list.sort(greater<int>());
    // 遍历
    for(list<int>::iterator temp=a_list.begin(); temp!=a_list.end(); temp++)
    {
        cout << *temp << " ";
    }
    cout<<endl;
    for(auto temp : a_list)
        cout << temp << " ";
    cout << endl;
	cout << "..........deque queue stack............" << endl<<endl;
    // deque queue stack是基于list实现的
    // deque由若干个buffer指针组成,每次扩充一个buffer
    deque<int> a_deque = {7, 5, 2, 1, 6, 8};
    sort(a_deque.begin(), a_deque.end(), less<int>());
    for(auto temp : a_deque)
        cout << temp << " ";
    cout << endl;
    cout << "..........multiset multimap............" << endl<<endl;
    /*第二类容器,关联容器,适合查找,都含有自带的find函数*/
    // multiset multimap 都是基于二叉树实现的会默认按照key排序
    multiset<int> a_multiset = {3, 1, 3, 2, 5, 8, 7};
    a_multiset.insert(20);
    auto target_multiset = a_multiset.find(7);
    if(target_multiset != a_multiset.end())
        cout << "multiset find " << *target_multiset << endl<<endl;
    for(auto temp : a_multiset)
        cout << temp << " ";
    cout << endl;
    multimap<int, string> a_multimap = {make_pair(1, "wuhan"),
                                        make_pair(5, "beijing"),
                                        make_pair(3, "dongfang"),};
    for(auto temp : a_multimap)
        cout << temp.first << "  " << temp.second << endl;
    auto target_multimap = a_multimap.find(5);
    cout << "multimap find " << (*target_multimap).first << " " << (*target_multimap).second << endl;
	cout << "..........unordered_map unordered_set............" << endl<<endl;
    // 类似的是unordered_map和unordered_set
    // 基于hash表实现的,其中key没有排序,但查找速度更快(O(1)),multiset复杂度为(O(log(n)))
    // 但也没有重复元素
    unordered_set<int> a_unordered_set = {3, 1, 3, 2, 5, 8, 7};
    a_unordered_set.insert(20);
    for(auto temp : a_unordered_set)
        cout << temp << " ";
    cout << endl;

    // 第二个相关的是set和map,基于红黑树实现的,已经排序了,这中间也没有重复元素!
    cout << "................set map..............." << endl<<endl;
    set<int> a_set = {3, 1, 3, 2, 5, 8, 7};
    for(auto temp : a_set)
        cout << temp << " ";

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值