OPP第二篇

**管理指针成员**
三种方法

 - 1.常规指针类(浅复制)

严重缺点:野指针(悬垂指针)
 - 2.智能指针类(计数类)

避免野指针(悬垂指针)
 - 3.值型类(深复制)

#pragma once
//常规指针类
class AHasPtr {
public:
	AHasPtr( int* p, int i) :ptr(p), val(i) {}

	int* get_ptr() const { return ptr; }
	int get_int() const { return val; }

	void set_ptr(int* p) { ptr = p; }
	void set_int(int i) { val = i; }

	int get_ptr_val() const { return *ptr; }
	void set_ptr_val(int val)const { *ptr = val; }
private:
	int val;
	int* ptr;
};
#pragma once
//值型类
class CHasPtr {
public:
	CHasPtr(const int &p, int i) :ptr(new int (p)), val(i) {}

	CHasPtr(const CHasPtr& orig)
		:ptr(new int(*orig.ptr)), val(orig.val) {}

	CHasPtr& operator=(const CHasPtr&);

	~CHasPtr() { delete ptr; }
	int* get_ptr() const { return ptr; }
	int get_int() const { return val; }

	void set_ptr(int* p) { ptr = p; }
	void set_int(int i) { val = i; }

	int get_ptr_val() const { return *ptr; }
	void set_ptr_val(int val)const { *ptr = val; }
private:
	int val;
	int* ptr;
};
CHasPtr& CHasPtr::operator=(const CHasPtr& rhs)
{
	*ptr = *rhs.ptr;
	val = rhs.val;
	return *this;
}
//#pragma once
//智能指针类
class U_ptr
{
	friend class BHasPtr;
private:
	int* ip;
	size_t use;//计数
	U_ptr(int* p) :ip(p), use(1) {}
	~U_ptr() { delete ip; }
};
class BHasPtr {
public:
	BHasPtr(int* p, int i) :ptr(new U_ptr(p)), val(i) {}
	BHasPtr(const BHasPtr& orig) :ptr(orig.ptr), val(orig.val)
	{
		++ptr->use;//计数加一
	}
	BHasPtr& operator=(const BHasPtr&);
	~BHasPtr()
	{
		if (--ptr->use == 0)delete ptr;
	}
	int* get_ptr() const { return ptr->ip; }
	int get_int()const { return val; }

	void set_ptr(int* p) { ptr->ip = p; }
	void set_int(int i) { val = i; }

	int get_ptr_val() const { return *ptr->ip; }
	void set_ptr_val(int val)const { *ptr->ip = val; }
private:
	int val;
	//int* ptr;
	U_ptr* ptr;
};
BHasPtr& BHasPtr::operator=(const BHasPtr& rhs)
{
	++rhs.ptr->use;//右边的加加
	if (--ptr->use == 0)delete ptr;//左边的减减
	ptr = rhs.ptr;
	val = rhs.val;
	return *this;
}

出了点小问题 和视频一样的代码 但是cpp中出现了报错 

#include<iostream>
#include"plain_ptr.h"
#include"value_ptr.h"
#include"smart_ptr.h"
using namespace std;

void test_AHasPtr()
{
	int i = 42;
	AHasPtr pl(&i, 42);
	AHasPtr P2 = pl;
	cout << P2.get_ptr_val() << endl;

	pl.set_ptr_val(0);
	cout << P2.get_ptr_val() << endl;

	int* ip = new int(42);
	AHasPtr ptr(ip, 10);
	cout << ptr.get_ptr_val() << endl;
	delete ip;
	cout << ptr.get_ptr_val() << endl;
}
void test_CHasPtr()
{
	int a, b;
	a = 5;
	b = a;
	b = 9;

	int obj = 0;

	CHasPtr ptr1(obj, 42);
	CHasPtr ptr2(ptr1);
	cout << ptr1.get_ptr_val() << "," << ptr1.get_int() << endl;
	cout << ptr2.get_ptr_val() << "," << ptr2.get_int() << endl;
	ptr2.set_ptr_val(6);
	ptr2.set_int(48);
	cout << "修改后:" << endl;
	cout << ptr1.get_ptr_val() << "," << ptr1.get_int() << endl;
	cout << ptr2.get_ptr_val() << "," << ptr2.get_int() << endl;
}
void test_BHasPtr()
{
	int obj = 0;
	BHasPtr ptr1(&obj, 42);
	BHasPtr ptr2(ptr1);
	cout << ptr1.get_ptr_val() << "," << ptr1.get_int() << endl;
	cout << ptr2.get_ptr_val() << "," << ptr2.get_int() << endl;
	cout << "修改以后:" << endl;
	ptr2.get_ptr_val(2);
	ptr2.set_int(22);
	cout << ptr1.get_ptr_val() << "," << ptr1.get_int() << endl;
	cout << ptr2.get_ptr_val() << "," << ptr2.get_int() << endl;
}


int main()
{
	cout << "常规指针:" << endl;
	test_AHasPtr();
	cout << "值型类:" << endl;
	test_CHasPtr();
test_BHasPtr();
	return 0;
}

重载操作符

  • 可以重载的操作符(42个)
  • + - * / % ^ & | ~... 
  • 不能重载的操作符
  • ::   .*   .    ?:
  • 重载操作符的注意事项
/*
 * This file contains code from "C++ Primer, Fifth Edition", by Stanley B.
 * Lippman, Josee Lajoie, and Barbara E. Moo, and is covered under the
 * copyright and warranty notices given in that book:
 *
 * "Copyright (c) 2013 by Objectwrite, Inc., Josee Lajoie, and Barbara E. Moo."
 *
 *
 * "The authors and publisher have taken care in the preparation of this book,
 * but make no expressed or implied warranty of any kind and assume no
 * responsibility for errors or omissions. No liability is assumed for
 * incidental or consequential damages in connection with or arising out of the
 * use of the information or programs contained herein."
 *
 * Permission is granted for this code to be used for educational purposes in
 * association with the book, given proper citation if and when posted or
 * reproduced.Any commercial use of this code requires the explicit written
 * permission of the publisher, Addison-Wesley Professional, a division of
 * Pearson Education, Inc. Send your request for permission, stating clearly
 * what code you would like to use, and in what specific way, to the following
 * address:
 *
 *     Pearson Education, Inc.
 *     Rights and Permissions Department
 *     One Lake Street
 *     Upper Saddle River, NJ  07458
 *     Fax: (201) 236-3290
*/

/* This file defines the Sales_item class used in chapter 1.
 * The code used in this file will be explained in
 * Chapter 7 (Classes) and Chapter 14 (Overloaded Operators)
 * Readers shouldn't try to understand the code in this file
 * until they have read those chapters.
*/

#ifndef SALESITEM_H
// we're here only if SALESITEM_H has not yet been defined
#define SALESITEM_H

// Definition of Sales_item class and related functions goes here
#include <iostream>
#include <string>

class Sales_item {
    // these declarations are explained section 7.2.1, p. 270
    // and in chapter 14, pages 557, 558, 561
    friend std::istream& operator>>(std::istream&, Sales_item&);//  重载>>操作符
    friend std::ostream& operator<<(std::ostream&, const Sales_item&);
    friend bool operator<(const Sales_item&, const Sales_item&);
    friend bool
        operator==(const Sales_item&, const Sales_item&);
public:
    // constructors are explained in section 7.1.4, pages 262 - 265
    // default constructor needed to initialize members of built-in type
#if defined(IN_CLASS_INITS) && defined(DEFAULT_FCNS)
    Sales_item() = default;
#else
    Sales_item() : units_sold(0), revenue(0.0) { }
#endif
    Sales_item(const std::string& book) :
        bookNo(book), units_sold(0), revenue(0.0) { }
    Sales_item(std::istream& is) { is >> *this; }
public:
    // operations on Sales_item objects
    // member binary operator: left-hand operand bound to implicit this pointer
    Sales_item& operator+=(const Sales_item&);

    // operations on Sales_item objects
    std::string isbn() const { return bookNo; }
    double avg_price() const;
    // private members as before
private:
    std::string bookNo;      // implicitly initialized to the empty string
#ifdef IN_CLASS_INITS
    unsigned units_sold = 0; // explicitly initialized
    double revenue = 0.0;
#else
    unsigned units_sold;
    double revenue;
#endif
};

// used in chapter 10
inline
bool compareIsbn(const Sales_item& lhs, const Sales_item& rhs)
{
    return lhs.isbn() == rhs.isbn();
}

// nonmember binary operator: must declare a parameter for each operand
Sales_item operator+(const Sales_item&, const Sales_item&);//重载了加法 操作

inline bool
operator==(const Sales_item& lhs, const Sales_item& rhs)
{
    // must be made a friend of Sales_item
    return lhs.units_sold == rhs.units_sold &&
        lhs.revenue == rhs.revenue &&
        lhs.isbn() == rhs.isbn();
}

inline bool
operator!=(const Sales_item& lhs, const Sales_item& rhs)
{
    return !(lhs == rhs); // != defined in terms of operator==
}

// assumes that both objects refer to the same ISBN
Sales_item& Sales_item::operator+=(const Sales_item& rhs)
{
    units_sold += rhs.units_sold;
    revenue += rhs.revenue;
    return *this;
}

// assumes that both objects refer to the same ISBN
Sales_item
operator+(const Sales_item& lhs, const Sales_item& rhs)重载了加法 操作
{
    Sales_item ret(lhs);  // copy (|lhs|) into a local object that we'll return
    ret += rhs;           // add in the contents of (|rhs|)
    return ret;           // return (|ret|) by value
}

std::istream&
operator>>(std::istream& in, Sales_item& s)
{
    double price;
    in >> s.bookNo >> s.units_sold >> price;
    // check that the inputs succeeded
    if (in)
        s.revenue = s.units_sold * price;
    else
        s = Sales_item();  // input failed: reset object to default state
    return in;
}

std::ostream&
operator<<(std::ostream& out, const Sales_item& s)//重载了 <<输出  操作符
{
    out << s.isbn() << " " << s.units_sold << " "
        << s.revenue << " " << s.avg_price();
    return out;
}

double Sales_item::avg_price() const
{
    if (units_sold)
        return revenue / units_sold;
    else
        return 0;
}
#endif
#include<iostream>
#include"Sales_item.h"

using namespace std;

class Person
{
	//重载操作符:加法
public:
	void operator+(const Person& rhs)
	{
		cout << "执行了重载的加法操作" << endl;
	}
	//void operator>>
};
int main()
{
	int a, b;
	a = 12;
	b = 9;
	//cin >> a;
	cout << a + b << endl;

	
	Person p1, p2;
	p1 + p2;

	Sales_item item1, item2;
	cin >> item1>>item2;
	cout<<item1 + item2<<endl;
	//cout << operator+(item1, item2) << endl;加法 operator+函数

	cout << "Hello" << endl;
	system("pause");
	return 0;
}

操作符重载2

  • 输出操作符<<重载
  • 非成员函数--友元函数
  • 少做格式化
  • 输入操作符>>重载
  •  处理输入操作的错误

 

#include<iostream>
#include<string>

using namespace std;

class Dog
{

};
class Sales_item
{
	friend ostream& operator <<(ostream& out, const Sales_item& s);
	friend istream& operator>>(istream& in, Sales_item& d);
public:
	Sales_item(string& book, unsigned units, double price) :
		isbn(book), units_sold(units), revenue(price*units) {}
	Sales_item() :units_sold(0), revenue(0.0) {}
	
private:
	string isbn;
	unsigned units_sold;
	double revenue;
};

ostream& operator <<(ostream& out, const Sales_item& s)
{
	out << s.isbn << "\t" << s.units_sold << "\t" << s.revenue;
	return out;
}

istream& operator>>(istream& in, Sales_item& d)
{
	double price;
	in >> d.isbn  >> d.units_sold>> price;//"\t"
	if (in)//进行错误检查
		d.revenue = d.units_sold * price;//这里注意一下
	else
		d = Sales_item();
	return in;
}
int main()
{
	Dog a;

	Sales_item item(string("0-201-78345-X"), 2, 25.00);

	cout << item<<endl;
	cout << "hello" << endl;

	cin >> item;
	cout << item << endl;
	system("pause");
	return 0;
}

操作符重载3

 1.算术操作符

+       +=

-        -=

*       *=

/       /=

%      %=

2.为了与内置操作符保持一致,算术操作符通常产生一个新值

3.一般应使用复合赋值实现算术操作符

例如:用+= 来实现 +

 

#include<iostream>

using namespace std;

class Dog
{
	
};
class Cat
{

};

class Sales_item
{

public:
	Sales_item(const string& book,const  unsigned units,const  double amount) :
		isbn(book), units_sold(units), revenue(amount) {}

	Sales_item& operator-=(const Sales_item&);
	Sales_item& operator+=(const Sales_item&);
	friend std::ostream& operator<<(std::ostream&, const Sales_item&);
private:
	string isbn;
	unsigned units_sold;
	double revenue;
};

Sales_item operator+(const Sales_item& lhs, const Sales_item& rhs);
Sales_item operator-(const Sales_item& lhs, const Sales_item& rhs);

Sales_item& Sales_item::operator+=(const Sales_item& rhs)
{
	this->units_sold += rhs.units_sold;
	this->revenue += rhs.revenue;
	return *this;
}
Sales_item& Sales_item::operator-=(const Sales_item& rhs)
{
	this->units_sold -= rhs.units_sold;
	this->revenue -= rhs.revenue;
	return *this;
}

Sales_item operator-(const Sales_item& lhs, const Sales_item& rhs)
{
	Sales_item ret(lhs);
	ret -= rhs;
	return ret;
}

Sales_item operator+(const Sales_item& lhs, const Sales_item& rhs)
{
	Sales_item ret(lhs);
	ret += rhs;
	return ret;
}
std::ostream& operator<<(std::ostream& out, const Sales_item& s)
{
	out << s.isbn << "\t" << s.units_sold << "\t" << s.revenue;
		return out;
}
int main()
{
	Dog dog;
	Cat cat;
	
	Sales_item item1(string("0-324-25325-X"), 10, 120.0);
	Sales_item item2(string("0-324-25325-X"), 20, 220.0);
	Sales_item result = item2 + item1;

	cout << result << endl;
	Sales_item item3(string("0-324-25325-X"), 5, 220.0);
	result += item3;
	cout << result << endl;

	result -= item2;
	cout << result << endl;

	result =item1- item2;
	cout << result << endl;

	cout << "hello" << endl;
	system("pause");
	return 0;
}

关系操作符重载

1.关系操作符

==      !=

<       <=

>         >=

2.最好相互联系起来进行重载,让一个操作符调用另一个操作符

#include<iostream>
#include"Sales_item.h"
#include<string>

using namespace std;

class Person
{
	//成员
	//bool operator==
};
int main()
{
	//Person a("232423634745","张飞");
	//Person b("232423634745","张飞");

	//if(a==b)


	Sales_item a("0-201-78345-X", 10,120.00);//字符串报错
	Sales_item b("0-201-78345-X", 10,120.00);

	if (a == b)
	{
		cout << "销售单a和b 是一样的" << endl;
	}
	system("pause");
	return 0;
}
#include<iostream>
#include"stdlib.h"
using namespace std;

class Date
{

public:
	Date(int m = 0, int d = 0, int y = 0) :month(m), day(d), year(y) {}
	int operator == (Date & dt) const;
	int operator != (Date& dt) const;
	int operator<(Date& dt)const;
	int operator<=(Date& dt)const;
	int operator>(Date& dt)const;
	int operator>=(Date& dt)const;
private:
	int month, day, year;

};
int Date::operator==(Date& dt)const
{
	return (this->month == dt.month) && (this->day == dt.day) && (this->year == dt.year);
}

int Date:: operator != (Date& dt) const
{
	return !(*this == dt);
}

int Date::operator<(Date& dt)const
{
	if (this->year == dt.year)
	{
		if (this->month == dt.month)
			return this->day < dt.day;
		return this->month < dt.month;
	}
}
int main()
{
	Date d1(2, 14, 2005);
	Date d2(6, 19, 2005);
	Date d3(2, 14, 2005);

	if (d1 < d2)
		cout << "d1小于d2" << endl;
	if (d1 == d3)
		cout << "d1等于d3" << endl;
	system("pause");
	return 0;
}

 赋值操作符重载

1.赋值操作符

=     +=    -=

*=    /=    %=

&=   |=   ^=

<<=       >==

2.赋值操作符必须返回对*this的引用

#include<iostream>

using namespace std;

class String
{
public:
	String(char const* chars = " ");

	String& operator=(String const&);
	String& operator=(char const&);
	String& operator=(char);


	void print();
private:
	char* ptrChars;
};

void String::print()
{
	cout << ptrChars << endl;
}
String& String::operator=(String const& str)
{
	if (strlen(ptrChars) != strlen(str.ptrChars))
	{
		char* ptrHold = new char[strlen(str.ptrChars) + 1];
		delete[] ptrChars;
		ptrChars = ptrHold;
	}
	std::strcpy(ptrChars, str.ptrChars);
	return *this;
}

String::String(char const* chars)
{
	chars = chars ? chars : "";
	ptrChars = new char[std::strlen(chars) + 1];
	std::strcpy(ptrChars, chars);
}

int main()
{
	String s("hello");
	String s2("Dog");

	s.print();
	s2.print();

	s = s2;
	s.print();

	/*s = "cat";*/
	
	system("pause");
	return 0;
}

 操作符重载

1.下标操作符

[]

2.两个版本

可变成员函数

常量成员函数

#include<iostream>

using namespace std;

class String
{
public:
	String(char const* chars = "");

	char& operator[](std::size_t index) throw(String);
	char operator[](std::size_t index)const throw(string);
	void print();

private:
	char* ptrChars;
	static String errorMessage;
};

void String::print()
{
	cout << *ptrChars << endl;
}

String String::errorMessage("Subscript out of range");
char& String::operator[](std::size_t index) throw(String)

{
	cout << "noconst " << endl;
	if (index >= std::strlen(ptrChars))
		throw errorMessage;
	return ptrChars[index];
}

char String::operator[](std::size_t index)const throw (String)
{
	cout << "const" << endl;
	if (index >= std::strlen(ptrChars))
		throw errorMessage;
	return ptrChars[index];
}

String::String(char const* chars)
{
	chars = chars ? chars : "";
	ptrChars = new char[std::strlen(chars) + 1];
	std::strcpy(ptrChars, chars);
}
int main()
{
	string a("C++");
	cout << a[0] << endl;

	String s("Hello");
	s.print();

	cout << s[0] << endl;

	s[0] = 'A';
	s.print();

	String const s2("dog");
	cout << s2[2] << endl;

	system("pause");
	return 0;
}

成员访问操作符

1.成员访问操作符

解引用操作符:*

箭头操作符:->

2.复习

管理指针成员

定义智能指针类

class Pointer-------class String

#pragma once
//#ifndef STRING_H
//#define STRING_H


class String
{
public:
	String(char const* chars = "");
	String(String const& str);
	~String();

	void display()const;
private:
	char* ptrChars;
};
String::String(char const* chars)
{
	chars = chars ? chars : "";
	ptrChars = new char[std::strlen(chars) + 1];
	std::strcpy(ptrChars, chars);
}

String::String(String const& str)
{
	ptrChars = new char[std::strlen(str.ptrChars) + 1];
	std::strcpy(ptrChars, str.ptrChars);
}
String::~String()
{
	delete[] ptrChars;
}
void String::display()const
{
	std::cout << ptrChars << std::endl;
}

//#endif // !STRING_H
#ifndef STRING_H
#define STRING_H
#include"string.h"

class String;

//智能指针:对指针使用进行计数
class Pointer
{
public:
	Pointer();
	Pointer(String const& n);
	~Pointer();

	String& operator*();
	String* operator->() const;

private:
	String *ptr;
	static String errorMessage;
};

Pointer::Pointer() :ptr(0) {}
Pointer::Pointer(String const& n)
{
	ptr = new String(n);
}


Pointer::~Pointer()
{
	delete ptr;
}

String Pointer::errorMessage("Unitial lized pointer");

String& Pointer::operator*()
{
	if (!ptr)
		throw errorMessage;
	return *ptr;
}

String* Pointer::operator->()const
{
	if (!ptr)
		throw errorMessage;
	return ptr;
}
#endif // !STRING_H
#include<iostream>
#include"string.h"
#include"pointer.h"
using namespace std;

int main()
{
	String a("hello String ");
	a.display();

	String* ps = &a;//普通指针
	ps->display();
	
	try 
	{
		Pointer pl("C++");
		pl->display();

		String s = *pl;
		s.display();

		Pointer p2;
		p2->display();
	}
	catch (String const& error)
	{
		error.display();

	}

	system("pause");
	return 0;
}

 自增自减操作符重载

1.自增、自减操作符

++

- -

2.重载前缀形式、后缀形式的自增自减操作符

operator++();

operator++(int);

 

#include<iostream>

using namespace std;

class String
{
public:
	String(char const* chars = "");
	String(String const& str);
	~String();

	void display() const;

	String& operator++();//前加加
	String const operator++(int);//前加加
	String& operator--();//前加加
	String const operator--(int);//前加加
private:
	char* ptrChars;
};

String& String::operator++()
{
	for (std::size_t i = 0;i < std::strlen(ptrChars);++i)
	{
		++ptrChars[i];

	}
	return *this;
}

String const String::operator++(int n)
{
	String copy(*this);
	++(*this);
	return copy;
}
void String::display() const
{
	cout << ptrChars << endl;
}

String::String(char const* chars)
{
	chars = chars ? chars : "";
	ptrChars = new char[std::strlen(chars) + 1];
	std::strcpy(ptrChars, chars);
}

String::String(String const& str)
{
	ptrChars = new char[std::strlen(str.ptrChars) + 1];
	std::strcpy(ptrChars, str.ptrChars);
}

String::~String()
{
	delete[] ptrChars;
}
int main()
{
	int x = 5;
	x++;
	++x;
	cout << x << endl;


	String s("ABC");
	s.display();


	++s;
	s.display();

	s++;
	s.display();

	cout << endl;

	String str1("ABC");
	str1.display();

	String str2("++str1");
	str2.display();

	String str3(str1++);
	str3.display();
	str1.display();

	//s--;
	//--s;
	system("pause");
	return 0;
}

 函数对象

1.重载函数调用操作符

2.函数对象:定义了调用操作符的类,其对象称为“函数对象”

3.一元函数对象

一元谓词 : 一元函数为bool时是一元谓词

4.二元函数对象

二元谓词

#include<iostream>
#include<vector>
#include<list>
#include<algorithm>

using namespace std;

//class absInt
//{
//public:
//int operator()(int val)
//{}
//};


//类
struct absInt
{//重载操作符:函数调用操作符
	int operator()(int val)
	{
		return val < 0 ? -val : val;
	}
};

template<typename elementType>
void FuncDisplayElement(const elementType& element)
{
	cout << element << ' ';
}
template<typename elementType>
struct DisplayElement
{
	//存储状态
	int m_nCount;

	DisplayElement()
	{
		m_nCount = 0;
	}

	void operator() (const elementType& element) 
	{
		++m_nCount;
		cout << element << ' ';
	}
};
int main()
{
	int i = -42;
	absInt absObj;
	unsigned int ui = absObj(i);//函数对象

	cout << ui << endl;

	vector<int> a;
	for (int n = 0;n < 10;++n)
		a.push_back(n);

	list<char> b;
	for (char c = 'a';c < 'k';++c)
		b.push_back(c);

	//STL算法
	DisplayElement<int> mResult;
	mResult=for_each(a.begin(), a.end(), mResult);
	cout << endl;
	cout << "数量:" << mResult.m_nCount<< endl;

	for_each(b.begin(), b.end(), DisplayElement<char>());

	cout << "hello 函数对象!" << endl;

	system("pause");
	return 0;
}

一元谓词

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

template<typename numberType>
struct IsMultiple
{
	numberType m_Divisor;

	IsMultiple(const numberType& divisor)
	{
		m_Divisor = divisor;
	}

	//重载
	bool operator()(const numberType& element) const//一元谓词
	{
		return ((element % m_Divisor) == 0);
	}
};



int main()
{
	vector<int>vecIntegers;
	for (int i = 33;i < 100;++i)
		vecIntegers.push_back(i);

	//IsMultiple<int> a(4);//函数对象

	vector<int>::iterator iElement;
	//                                                             匿名函数对象
	iElement=find_if(vecIntegers.begin(), vecIntegers.end(), IsMultiple<int>(4));
	if (iElement != vecIntegers.end())
	{
		cout << "第一个4的整数倍的数是;" << *iElement<<endl;
	}

	return 0;
}

二元谓词

#include<iostream>
#include<algorithm>
#include<vector>

template<typename elementType>//二元模板
class CMultiply //乘法
{
public:
	elementType operator()(const elementType& elem1, const elementType& elem2)
	{
		return elem1 * elem2;
	}
};

int main()
{
	using namespace std;

	vector<int>a, b;
	for (int i = 0;i < 10;++i)
		a.push_back(i);

	for (int j = 100;j < 110;++j)
		b.push_back(j);

	vector<int>vecResult;
	vecResult.resize(10);

	//算法
	transform(a.begin(), a.end(), b.begin(), vecResult.begin(), CMultiply<int>());

	for (size_t nIndex = 0;nIndex < vecResult.size();++nIndex)
		cout << vecResult[nIndex] << ' ';
	cout << endl;

	cout << "二元函数对象!" << endl;

	return 0;
}

二元谓词 不分大小写

#include<iostream>
#include<set>
#include<string>
#include<algorithm>

using namespace std;

class CCompareStringNoCase
{
public:
	bool operator()(const string& str1, const string& str2)const
	{
		string str1LowerCase;
		str1LowerCase.resize(str1.size());
		transform(str1.begin(), str1.end(), str1LowerCase.begin(), tolower);

		string str2LowerCase;
		str2LowerCase.resize(str2.size());
		transform(str2.begin(), str2.end(), str2LowerCase.begin(), tolower);

		return (str1LowerCase<str2LowerCase);
	}



};
int main()
{

	set<string, CCompareStringNoCase> names;//二元谓词 改变容器set 不分大小写
	names.insert("Tina");
	names.insert("jim");
	names.insert("Jack");
	names.insert("sam");
	names.insert("Hello");

	set<string, CCompareStringNoCase>::iterator iNameFound = names.find("Jim");
	if (iNameFound != names.end())
	{
		cout << "找到了:"<<*iNameFound << endl;
	}
	else
	{
		cout << "没找到!" << endl;
	}
	return 0;
}

转换操作符

1.转换函数

operator int () const;

2.注意

  • 必须是成员函数
  • 不能指定返回类型
  • 形参必须是空的
  • 必须显示地返回一个指定类型的值
  • 不应该改变被转换对象,通常定义为const
/*
 * This file contains code from "C++ Primer, Fifth Edition", by Stanley B.
 * Lippman, Josee Lajoie, and Barbara E. Moo, and is covered under the
 * copyright and warranty notices given in that book:
 *
 * "Copyright (c) 2013 by Objectwrite, Inc., Josee Lajoie, and Barbara E. Moo."
 *
 *
 * "The authors and publisher have taken care in the preparation of this book,
 * but make no expressed or implied warranty of any kind and assume no
 * responsibility for errors or omissions. No liability is assumed for
 * incidental or consequential damages in connection with or arising out of the
 * use of the information or programs contained herein."
 *
 * Permission is granted for this code to be used for educational purposes in
 * association with the book, given proper citation if and when posted or
 * reproduced.Any commercial use of this code requires the explicit written
 * permission of the publisher, Addison-Wesley Professional, a division of
 * Pearson Education, Inc. Send your request for permission, stating clearly
 * what code you would like to use, and in what specific way, to the following
 * address:
 *
 *     Pearson Education, Inc.
 *     Rights and Permissions Department
 *     One Lake Street
 *     Upper Saddle River, NJ  07458
 *     Fax: (201) 236-3290
*/

/* This file defines the Sales_item class used in chapter 1.
 * The code used in this file will be explained in
 * Chapter 7 (Classes) and Chapter 14 (Overloaded Operators)
 * Readers shouldn't try to understand the code in this file
 * until they have read those chapters.
*/

#ifndef SALESITEM_H
// we're here only if SALESITEM_H has not yet been defined
#define SALESITEM_H  

// Definition of Sales_item class and related functions goes here
#include <iostream>
#include <string>

class Sales_item {
    // these declarations are explained section 7.2.1, p. 270
    // and in chapter 14, pages 557, 558, 561
    friend std::istream& operator>>(std::istream&, Sales_item&);//  重载>>操作符
    friend std::ostream& operator<<(std::ostream&, const Sales_item&);
    friend bool operator<(const Sales_item&, const Sales_item&);
    friend bool
        operator==(const Sales_item&, const Sales_item&);
public:
    // constructors are explained in section 7.1.4, pages 262 - 265
    // default constructor needed to initialize members of built-in type
#if defined(IN_CLASS_INITS) && defined(DEFAULT_FCNS)
    Sales_item() = default;
#else
    Sales_item() : units_sold(0), revenue(0.0) { }
#endif
    Sales_item(const std::string& book) :
        bookNo(book), units_sold(0), revenue(0.0) { }
    Sales_item(std::istream& is) { is >> *this; }
public:
    // operations on Sales_item objects
    // member binary operator: left-hand operand bound to implicit this pointer
    Sales_item& operator+=(const Sales_item&);

    // operations on Sales_item objects
    std::string isbn() const { return bookNo; }
    double avg_price() const;
    // private members as before

public:
    Sales_item(const std::string& book,unsigned units,double amount) :
        bookNo(book), units_sold(units_sold), revenue(amount) { }

   // Sales_item() : units_sold(0), revenue(0.0) { }
    operator double() const;
    operator std::string()const;

private:
    std::string bookNo;      // implicitly initialized to the empty string
#ifdef IN_CLASS_INITS
    unsigned units_sold = 0; // explicitly initialized
    double revenue = 0.0;
#else
    unsigned units_sold;
    double revenue;
#endif
};

Sales_item::operator double()const
{
    return revenue;
}

Sales_item::operator std::string() const
{
    return  bookNo;
}
// used in chapter 10
inline
bool compareIsbn(const Sales_item& lhs, const Sales_item& rhs)
{
    return lhs.isbn() == rhs.isbn();
}

// nonmember binary operator: must declare a parameter for each operand
Sales_item operator+(const Sales_item&, const Sales_item&);//重载了加法 操作

inline bool
operator==(const Sales_item& lhs, const Sales_item& rhs)
{
    // must be made a friend of Sales_item
    return lhs.units_sold == rhs.units_sold &&
        lhs.revenue == rhs.revenue &&
        lhs.isbn() == rhs.isbn();
}

inline bool
operator!=(const Sales_item& lhs, const Sales_item& rhs)
{
    return !(lhs == rhs); // != defined in terms of operator==
}

// assumes that both objects refer to the same ISBN
Sales_item& Sales_item::operator+=(const Sales_item& rhs)
{
    units_sold += rhs.units_sold;
    revenue += rhs.revenue;
    return *this;
}

// assumes that both objects refer to the same ISBN
Sales_item
operator+(const Sales_item& lhs, const Sales_item& rhs)重载了加法 操作
{
    Sales_item ret(lhs);  // copy (|lhs|) into a local object that we'll return
    ret += rhs;           // add in the contents of (|rhs|)
    return ret;           // return (|ret|) by value
}

std::istream&
operator>>(std::istream& in, Sales_item& s)
{
    double price;
    in >> s.bookNo >> s.units_sold >> price;
    // check that the inputs succeeded
    if (in)
        s.revenue = s.units_sold * price;
    else
        s = Sales_item();  // input failed: reset object to default state
    return in;
}

std::ostream&
operator<<(std::ostream& out, const Sales_item& s)//重载了 <<输出  操作符
{
    out << s.isbn() << " " << s.units_sold << " "
        << s.revenue << " " << s.avg_price();
    return out;
}

double Sales_item::avg_price() const
{
    if (units_sold)
        return revenue / units_sold;
    else
        return 0;
}
#endif

 

#include<iostream>
#include<string>
#include"Sales_item.h"

using namespace std;


class Dog
{
public:
	Dog(string n, int a, double w) :name(n), age(a), weight(w) {}
	//不能指定返回类型 形参表()
	operator int() const//转换函数 const
	{
		return age;//显示返回指定类型的值
	}
	operator double() const
	{
		return weight;
	}
private:
	int age;
	double weight;
	string name;

};
int main()
{
	int a, b;

	a = 10;
	b = a;

	Dog d("Bil",6,15.0);
	b = d;

	cout << b << endl;

	Sales_item item("x-123-2423",10,120.0);
	double m;
	m = item;
	cout << m << endl;
	cout << item << endl;

	string s = item;
	cout << s << endl;

	system("pause");
	return 0;
}

定义基类和派生类

1.基类

virtual函数

protected成员

2.派生类

类派生列表

重定义virtual函数

可以访问基类的public和protected成员

#include<iostream>
#include<string>
using namespace std;

class Animal
{
	//成员略
}; 

class Dog : public Animal //:表示继承
{
      //成员略
};

class Cat : public Animal
{
	//
};

class Item_base
{
public:
	/*int x;*/
	Item_base(const std::string& book = " ", 
		double sales_price = 0.0):isbn(book),price(sales_price) {}
	std::string book() const
	{
		return isbn;

	}
	virtual double net_price(size_t n) const//虚函数 派生类可以修改
	{
		return n * price;
	}
private:
	std::string isbn;
protected://受保护的成员 专门用来做继承
	double price;

};
//    批量购买
class Bulk_item : public Item_base
{
public:

	Bulk_item(const std::string& book = " ",
		double sales_price = 0.0,
		size_t qty = 0,
		double disc_rate = 0.0) :
		Item_base(book, sales_price), min_qty(qty), discount(disc_rate) {}

	void test()
	{
	/*	cout << x << endl;*/
		cout << price << endl;//受保护的成员 专门用来做继承
	}
	void test2(const Bulk_item& d, const Item_base& b)
	{
	/*	cout << d.x << endl;
		cout << b.x << endl;*/
		cout << d.price << endl;
		//cout << b.price << endl;不行
	}

	//重写 (虚函数才能重写)
	double net_price(size_t cnt) const
	{
		if (cnt >= min_qty)
			return cnt * (1 - discount) * price;
		else
			return cnt * price;
	}
private:
	size_t min_qty;
	double discount;
};
int main()
{
	Animal a;
	Dog d;
	Cat c;

	Item_base item("0-12-1432-3",9.9);
	cout <<item.book()<<","<< item.net_price(10) << endl;

	//cout << item.x << endl;
	/*cout << item.isbn << endl;*/

	Bulk_item item2("0-12-1432-3",9.9,10,0.12);
	cout <<item2.book()<<","<< item2.net_price(10) << endl;
	/*cout << item2.x << endl;*/

	item2.test();
	item2.test2(item2, item);
	system("pause");
	return 0;
}

动态绑定

1.多态性

2.从派生类到基类的转换

3.引用或指针既可以指向基类对象,也可以指向派生类对象

4.只有通过引用或指针调用虚函数才会发生动态绑定

#include<iostream>

using namespace std;
class Item_base
{
public:

	Item_base(const std::string& book = " ",
		double sales_price = 0.0) :isbn(book), price(sales_price) {}
	std::string book() const
	{
		return isbn;

	}
	virtual double net_price(size_t n) const//虚函数 派生类可以修改
	{
		return n * price;
	}
private:
	std::string isbn;
protected://受保护的成员 专门用来做继承
	double price;

};
//    批量购买
class Bulk_item : public Item_base
{
public:

	Bulk_item(const std::string& book = " ",
		double sales_price = 0.0,
		size_t qty = 0,
		double disc_rate = 0.0) :
		Item_base(book, sales_price), min_qty(qty), discount(disc_rate) {}

	

	//重写 (虚函数才能重写)
	double net_price(size_t cnt) const
	{
		if (cnt >= min_qty)
			return cnt * (1 - discount) * price;
		else
			return cnt * price;
	}
private:
	size_t min_qty;
	double discount;
};

void print_total(ostream& os, Item_base* item, size_t n)
{
	os << "ISDN:" << item->book() << "\t number sold:" << n << "\t total price:" <<item->net_price(n)<< endl;
}
int main()
{
	Item_base* a = new Item_base("1-234-567-01", 11.0);
	Bulk_item* b = new Bulk_item("1-234-567-02", 22.0, 2, 0.05);

	print_total(cout, a, 2);
	print_total(cout, b, 3);

	Item_base* books[5];
	books[0] = new Item_base("0-123-456-01", 10.0);
	books[1] = new Bulk_item("0-123-456-02", 20.0, 6, 0.05);
	books[2] = new Item_base("0-123-456-03", 30.0);
	books[3] = new Bulk_item("0-123-456-04", 40.0, 4, 0.15);
	books[4] = new Bulk_item("0-123-456-05", 50.0, 2, 0.18);

	int num[5];
	num[0] = 2;
	num[1] = 10;
	num[2] = 1;
	num[3] = 5;
	num[4] = 3;

	//动态绑定   多态的效果
	for (int i = 0; i < 5; i++)
	{
		print_total(cout, books[i], num[i]);
	}

	system("pause");
	return 0;

}

三种继承

1.公有、私有、受保护的继承

  • class B :public A  接口继承(一般用这个)
  • class B:private A  实现继承
  • class B:protected A  实现继承

2.接口继承和实现继承

3.修改继承访问(去除个别成员)

using A::a;//把a变为公有的

4.默认继承访问级别 

#include<iostream>

using namespace std;

class A
{
public:
	//构造函数 初始化 否则b1报错
	A()
	{
		a = 10;
		b = 20;
		c = 30;
	}
	int a;
	int a2;
private:
	int c;
protected:
	int b;

};

class B1 : public A
{
public:
	void test()
	{
		cout << a << endl;
		cout << b << endl;
	//	cout << c << endl;不能用c
	}
};
//          私有继承
class B2 : private A
{
public:
	using A::a;//把a变为公有的
	void test()
	{
		cout << a << endl;
		cout << b << endl;
		//	cout << c << endl;不能用c
	}
};

class B3 : protected A
{
public:
	void test()
	{
		cout << a << endl;
		cout << b << endl;
		//	cout << c << endl;不能用c
	}
};
class C : public B1
{
public:
	void test()
	{
		cout << a << endl;
		cout << b << endl;
		//	cout << c << endl;不能用c
	}

};


class B4 : A  //默认private 私有继承
{
	int x; //默认private 私有继承
};

struct B5 : A  //默认public
{
	int m;//默认public
};
int main()
{
	B1 b1;
	b1.a;
	cout << b1.a << endl;
	b1.test();
	/*b1.b;
	b1.c;*///b和c在类B1里面能用 在main里面不能用

	B2 b2;
	b2.test();
//	b2.a;

	B3 b3;
	b3.test();
	//b3.a;
	system("pause");
	return 0;
}

 课程提纲:派生类的析构函数和构造函数

1.派生类的构造函数  

  • 执行基类的构造函数
  • 执行成员对象的构造函数
  • 执行派生类的构造函数

2.派生类的析构函数

  • 对派生类新增普通成员进行清理
  • 调用成员对象析构函数
  • 调用基类析构函数 

 

#include<iostream>

using namespace std;


class 老子
{
	//成员:很多行代码
public:
	int x;
};

class 小子 : public 老子
{
	//新的成员
public:
	int y;
};

class Base1
{
public:
	Base1(int i)
	{
		b1 = i;
		cout << "Base1的构造函数被调用" << endl;
	}

	void Print()const
	{
		cout << b1 << endl;
	}
private:
	int b1;
};

class Base2
{
public:
	Base2(int i)
	{
		b2 = i;
		cout << "Base2的构造函数被调用" << endl;
	}

	void Print()const
	{
		cout << b2 << endl;
	}
private:
	int b2;
};

class Base3
{
public:
	Base3()
	{
		b3 = 0;
		cout << "Base3的构造函数被调用" << endl;
	}

	void Print()const
	{
		cout << b3 << endl;
	}
private:
	int b3;
};


class Member
{
public:
	Member(int i)
	{
		m = i;
		cout << "Member 的构造函数被调用" << endl;
	}

	int GetM()
	{
		return m;
	}
private:
	int m;
};


//派生类  调用的顺序以下面这个为准
class Derived : public Base2, public Base1, public Base3
{
public:

	Derived(int i, int j, int k, int l);
	void Print();
private:
	int d;
	Member mem;
};

void Derived::Print()
{
	Base1::Print();
	Base2::Print();
	Base3::Print();
	cout << mem.GetM() << endl;
	cout << d << endl;
}

Derived::Derived(int i, int j, int k, int l) : Base1(i), Base2(j), mem(k)
{
	d = l;
	cout << "Derived的构造函数被调用:" << endl;

}
int main()
{
	小子 a;//a是小子,创建小子对象,先创建/构造老子!
	a.x=1;
	a.y=2;

	Derived obj(1, 2, 3, 4);
	obj.Print();

	system("pause");
	return 0;
}

析构函数和构造函数顺序相反(穿脱原则:先穿的后脱)

#include<iostream>

using namespace std;

class Base
{
public:
	Base()
	{
		b1 = b2 = 0;
	}
	Base(int i, int j);
	~Base();
	void Print()
	{
		cout << b1 << "," <<b2<<","<< endl;
	}
private:
	int b1, b2;


};

Base::Base(int i, int j)
{
	b1 = i;
	b2 = j;
	cout << "Base的析构函数被调用:" << b1<<","<<b2<<",";//","可以接上后面的
}

Base::~Base()
{
	cout<<"Base 的析构函数被调用:"<<b1 << "," << b2 << endl;
}

class Derived : public Base
{
public:
	Derived()
	{
		d = 0;
	}
	Derived(int i, int j, int k);
	~Derived();
	void Print();
private:
	int d;
};

Derived::Derived(int i, int j, int k) : Base(i, j), d(k)
{
	cout << "Derived的构造函数被调用:" <<d<< endl;
}

Derived::~Derived()
{
	cout << "Derived的析构函数被调用:" << d << endl;
}


void Derived::Print()
{
	Base::Print();
	cout << d << endl;
}
int main()
{
	Derived objD1(1, 2, 3), objD2(-4, -5, -6);
	objD1.Print();
	objD2.Print();

	return 0;
}

#include<iostream>


using namespace std;
enum BREED {GOLDEN, CAIRN, DANDIE,SHETLAND,LAB};//枚举
class Mamma1
{
public:
	Mamma1();
	~Mamma1();
	//封装  存取器成员函数
	int GetAge() const { return itsAge; }
	void SetAge(int age) { itsAge = age; }
	int GetWeight() const { return itsWeight; }
	void SetWeight(int weight) { itsWeight = weight; }

	void Speak()const { cout << "Mammal的声音!\n"; }
	void Sleep()const { cout << "shhh. I'm sleeping.\n"; }

protected:
	int itsAge;
	int itsWeight;
};


class Dog : public Mamma1
{
public:
	Dog();
	~Dog();
	
	BREED GetBreed() const { return itsBreed; }
	void SetBreed(BREED breed) { itsBreed = breed; }

	void WagTail() const { cout << "Tail wagging ...\n";}
	void BegForFood() const { cout << "Begging for food...\n"; }

private:
	BREED itsBreed;
};

Mamma1::Mamma1() : itsAge(3), itsWeight(5)
{
	cout << "Mamma1的构造函数..." << endl;
}

Mamma1::~Mamma1()
{
	cout << "Mamma1的析构函数..." << endl;
}

Dog::Dog() : itsBreed(GOLDEN)
{
	cout << "Dog的构造函数被调用..." << endl;
}

Dog::~Dog()
{
	cout << "Dog的析构函数被调用..." << endl;
}
int main()
{
//	Mamma1
	Dog Fido;
	Fido.Speak();
	Fido.WagTail();
	cout << "Fido is" << Fido.GetAge() << "years old" << endl;

	return 0;
}

转换与继承

1.派生类\rightarrow基类

引用转换/指针转换 ( 没问题 动态绑定 多态)

对象转换(有问题)

2.基类\rightarrow派生类

基类到派生类的自动转换不存在

强制转换

 

#include<iostream>
#include<string>
using namespace std;


class Item_base
{
public:
	
	Item_base(const std::string& book = " ",
		double sales_price = 0.0) :isbn(book), price(sales_price) {}
	std::string book() const
	{
		return isbn;

	}
	virtual double net_price(size_t n) const//虚函数 派生类可以修改
	{
		return n * price;
	}
private:
	std::string isbn;
protected://受保护的成员 专门用来做继承
	double price;

};
//    批量购买
class Bulk_item : public Item_base
{
public:

	Bulk_item(const std::string& book = " ",
		double sales_price = 0.0,
		size_t qty = 0,
		double disc_rate = 0.0) :
		Item_base(book, sales_price), min_qty(qty), discount(disc_rate) {}

	void test()
	{
		
		cout << price << endl;//受保护的成员 专门用来做继承
	}
	void test2(const Bulk_item& d, const Item_base& b)
	{
	
		cout << d.price << endl;

	}

	//重写 (虚函数才能重写)
	double net_price(size_t cnt) const
	{
		if (cnt >= min_qty)
			return cnt * (1 - discount) * price;
		else
			return cnt * price;
	}
private:
	size_t min_qty;
	double discount;
};
//                                       对象
void print_total_1(ostream& os, const Item_base item, size_t n)
{
	os << "ISBN:" << item.book() << "\tnumber sold:" << n << "\ttotal price:" << item.net_price(n) << endl;
}
//                                              指针
void print_total_2(ostream& os, const Item_base* item, size_t n)
{
	os << "ISBN:" << item->book() << "\tnumber sold:" << n << "\ttotal price:" << item->net_price(n) << endl;
}
//                                       引用
void print_total_3(ostream& os, const Item_base &item, size_t n)
{
	os << "ISBN:" << item.book() << "\tnumber sold:" << n << "\ttotal price:" << item.net_price(n) << endl;
}

int main()
{


	Item_base item("0-12-1432-3", 9.9);
	Bulk_item item2("0-12-1432-3", 9.9, 10, 0.12);

	print_total_1(cout, item, 10);
	print_total_1(cout, item2, 10);//这是对象转换,对象转换有问题 不打折(应该打折的)

	cout << endl;

	print_total_2(cout, &item, 10);
	print_total_2(cout, &item2, 10);//指针转换 没问题 动态绑定 多态

	cout << endl;

	print_total_3(cout, item, 10);
	print_total_3(cout, item2, 10);//引用转换 没问题 动态绑定 多态

	item = item2;
	//item2 = item;不行
	//Bulk_item* p = &item;不行
	//Bulk_item p = static_cast<Bulk_item>(item); //不用指针和引用 不行

	Bulk_item* p = static_cast<Bulk_item*>(&item);//强制转换没问题
	cout << p->net_price(10) << endl;

	system("pause");
	return 0;  
}

友元与继承

1.友元可以访问类的private和protected成员

2.友元关系不能继承 要明确授予友元

 

#include<iostream>

using namespace std;
//你爸爸
class Base 
{
	friend class Frnd;
	friend class D2;
protected:
	int i;
};

//你
class D1 : public Base
{
	friend class Frnd;
	friend class D2;
private:
	int j;
};

//我爸爸
class Frnd {
public:
	int mem(Base b) { return b.i; }
	int mem(D1 d) { return d.j; }
};
//我
class D2 : public Frnd {
public:

	int mem(Base b) { return b.i; }
	int mem(D1 d) { return d.j; }
};
int main()
{

	Base a;
	D1 b;
	Frnd c;
	D2 d;

	system("pause");
	return 0;
}

 静态成员与继承

1.基类中的static成员,在整个继承层次中只有一个实例

2.在派生类中访问static成员的方法

  • 基类名::成员名
  • 子类名::成员名
  • 对象.成员名
  • 指针-—— >成员名
  • 成员名
#include<iostream>

using namespace std;

class A
{
public:
	static std::size_t object_count()
	{
		return 100;
	}
protected:
	static const std::size_t obj_count=99;
};

class B : public A
{
public:
	void f(const B & b,B *b2)
	{
		
		//静态成员变量调用
		cout << A::obj_count << endl;
		cout << B::obj_count << endl;
		cout << b.obj_count << endl;
		cout << obj_count << endl;
		cout << b2->obj_count << endl;

		//静态成员函数调用
		cout << A::object_count() << endl;
		cout << B::object_count() << endl;
		cout << b.object_count() << endl;
		cout << b2->object_count() << endl;
		cout << object_count() << endl;
	}
};

class C : public B
{

};
int main()
{
	B b;
	b.f(b,&b);

	system("pause");
	return 0;
}

 

纯虚函数与抽象对象  

1.纯虚函数

2.抽象类--抽象数据类型

  • 任何包含一个或多个纯虚函数的类都是抽象类
  • 不要创建这个类的对象,应该继承它
  • 务必覆盖从这个类继承的纯虚函数

3.实现纯虚函数

4.C++接口

  • 就是只包含纯虚函数的抽象基类 

 

 

#include<iostream>

using namespace std;

//这个类是一个抽象类 --抽象数据类型
class Shape
{
public:
	Shape() {}
	virtual ~Shape() {}
	virtual double GetArea()=0;
	virtual double GetPerim()=0;//纯虚函数
	virtual void Draw() = 0;
};
//因为这是一个纯虚函数,可以不写,一般也都不写!
void Shape::Draw()
{
	cout << "...";
}
class Circle : public Shape
{
	//没有覆盖!
public:
	Circle(int radius) : itsRadius(radius){}
		virtual ~Circle() {}
	double GetArea() {return 3.14 * itsRadius * itsRadius;}
	double GetPerim() { return 2* 3.14 * itsRadius ; }
	void Draw();
private:
	int itsRadius;
};

void Circle::Draw()
{
	cout << "Circle drawing routine here!\n ";
}
class Rectangle : public Shape
{
public:
	Rectangle(int len,int width): itsWidth(width),itsLength(len) {}
	virtual ~Rectangle() {}
	double GetArea() { return itsLength * itsWidth; }
	double GetPerim() { return 2 * itsWidth + 2 * itsLength; }
	virtual int GetLength() { return itsLength; }
	virtual int GetWidth() { return itsWidth; }
	void Draw();

private:
	int itsWidth;
	int itsLength;
};

void Rectangle::Draw()
{

	for (int i = 0;i < itsLength;i++)
	{
		for (int j = 0;j < itsWidth;j++)
			cout << "x";

		cout << "\n";
	}
	Shape::Draw();
}
class Square : public  Rectangle
{
public:
	Square(int len);
	Square(int len, int width);
	virtual ~Square() {}
	double GetPerim() { return 4 * GetLength(); }
};


Square::Square(int len) : Rectangle(len, len) {}
Square::Square(int len, int width) : Rectangle(len, width)
{
	if (GetLength() != GetWidth())
		cout << "Error, not a square... a Rectangle??\n";
}
int main()
{
	//Shape a; 不能创建抽象类对象
	//Circle b;没覆盖报错
	//Circle b(3);
	//b.Draw();

	//Rectangle c(5, 8);
	//c.Draw();
	//cout << endl;
	//Square d(7);
	//d.Draw();

	int choice;
	bool fQuit = false;
	Shape *sp;

	while (fQuit == false)
	{
		cout << "(1)Circle (2)Rectangle (3)Square(0)Quit:";
		cin >> choice;

		switch (choice)
		{
		case 1:
			sp = new Circle(5);
			break;
		case2:
			sp = new Rectangle(4, 6);
			break;
		case 3:
			sp = new Square(5);
			break;
		case 0:
			fQuit = true;
			break;
		}
		if (fQuit == false)
		{
			sp->Draw();//多态  sp没有初始化 有问题
			delete sp;//new
			cout << endl;
		}
	}

	return 0;
}

#include<iostream>

using namespace std;

enum COLOR {Red,Green,Blue,Yellow,White,Black,Brown};
class Animal
{
public:
	Animal(int);
	virtual ~Animal() { cout << "Animal 析构函数被调用...\n"; }
	virtual int GetAge()const { return itsAge; }
	virtual void SetAge(int age) { itsAge = age; }
	virtual void Sleep()const = 0;
	virtual void Eat() const = 0;
	virtual void Reproduce()const = 0;//生孩子
	virtual void Move() const = 0;
	virtual void Speak() const = 0;
private:
	int itsAge;
};

Animal::Animal(int age) : itsAge(age)
{
	cout << "Animal 构造函数被调用...\n";
}
class Mammal : public Animal
{
public:
	Mammal(int age) :Animal(age)
	{
		cout << "Mammal构造函数被调用...\n";
	}
	virtual ~Mammal() { cout << "Mammal构造函数被调用...\n"; }
	virtual void Reproduce() const 
	{
		cout << "Mammal reproduction depicted...\n";
	}
};

class Fish : public Animal
{
public:
	Fish(int age) : Animal(age)
	{
		cout << "Fish 构造函数被调用...\n";
	}
	virtual ~Fish()
	{
		cout << "Fish 析构函数被调用...\n";
	}
	virtual void Sleep()const { cout << "Fish snoring...\n"; }
	virtual void Eat()const { cout << "Fish feeding ...\n"; }
	virtual void Reproduce()const { cout << "fish laying eggs...\n"; }
	virtual void Move()const { cout << "fish swimming...\n"; }
	virtual void Speak()const {}
};

class Horse : public Mammal
{
public:
	Horse(int age, COLOR color) : Mammal(age), itsColor(color)
	{
		cout << "Horse构造函数被调用...\n";
	}
	virtual ~Horse()
	{
		cout << "Horse析构函数被调用...\n";
	}

	virtual void Speak() const { cout << "Whinny!...\n"; }
	virtual void Sleep() const { cout << "Horse snoring ...\n"; }
	virtual COLOR GetItsColor()const { return itsColor; }
	virtual void Eat()const { cout << "Horse feeding...\n"; }
	virtual void Move() const { cout << "Horse running...\n "; }

protected:
	COLOR itsColor;
};

class Cat : public  Mammal
{
public:
	Cat(int age, COLOR color) : Mammal(age), itsColor(color)
	{
		cout << "Cat构造函数被调用...\n";
	}
	virtual ~Cat()
	{
		cout << "Cat析构函数被调用...\n";
	}

	virtual void Speak() const { cout << "Whoof!...\n"; }
	virtual void Sleep() const { cout << "Cat snoring ...\n"; }
	virtual void Eat()const { cout << "Cat feeding...\n"; }
	virtual void Move() const { cout << "Cat running...\n "; }
	virtual void Reproduce() const
	{
		cout << "Cats reproducing ...\n";
	}
protected:
	COLOR itsColor;
};
int main()
{
	Animal* pAnimal = 0;
	int choice;
	bool fQuit = false;

	while (fQuit == false)
	{
		cout << "(1)Cat (2)Horse (3)Fish (0)Quit:";
		cin >> choice;

		switch (choice)
		{
		case1:
			pAnimal = new Cat(5, Brown);
			break;
		case2:
			pAnimal = new Horse(4, Black);
			break;
		case 3:
			pAnimal = new Fish(5);
			break;
		default:
			fQuit == true;
			break;
		}
		if (fQuit == false)
		{
		//	pAnimal->Speak();
			pAnimal->Eat();
			pAnimal->Reproduce();
			pAnimal->Move();
			pAnimal->Sleep();
			delete pAnimal;
			cout << endl;
		}
	}
	return 0;
}

 模版与范型编程

1.两种模板

类模板、函数模板

2.范型编程

主要用于容器、迭代器、算法----> C++ STL标准模板库

3.示例

  • 普通队列
  • C++中的范型队列
  • 顺序队列
  • 链式队列

普通队列: 

#include<iostream>
#include<iomanip>

using namespace std;

class Queue
{

	struct Node
	{
		int a;
		Node* next;
	};
public:
	Queue();
	void push(int b);
	void pop();
	int getlength();
	virtual void print();

private:
	Node* head;
	Node* rear;
};

void Queue::push(int b)
{
	Node* p1 = new Node;
	p1->a = b;
	p1->next = NULL;
	rear->next = p1;
	rear = p1;
	head->a++;
	cout << setw(2) << b << setw(2) << "进入队列" << endl;
}

void Queue::pop()
{
	Node* p;
	p = head->next;
	cout << " " << setw(2) << p->a << setw(2) << "出队" << endl;
	head->next = p->next;
	delete p;
	head->a--;
}

int Queue::getlength()
{
	return head->a;
}

void Queue::print()
{
	Node* p;
	p = head->next;
	cout << "队列中的函数元素是:" << endl;
	while (p)
	{
		cout << p->a << "->";
		p = p->next;

	}
}

Queue::Queue()
{
	rear = head = new Node();
}

普通队列加模板(出了点小问题) 

 

#include<iostream>
#include<iomanip>

using namespace std;
//没改好 再改改
template<class T>//类模板
class Queue
{

	struct Node
	{
		T a;
		Node* next;
	};
public:
	Queue();
	void push(T b);
	void pop();
	int getlength();
	virtual void print();

private:
	Node* head;
	Node* rear;
};

template<class T>//类模板
void Queue::push(T b)
{
	Node* p1 = new Node;
	p1->a = b;
	p1->next = NULL;
	rear->next = p1;
	rear = p1;
	head->a++;
	cout << setw(2) << b << setw(2) << "进入队列" << endl;
}

template<class T>//类模板
void Queue::pop()
{
	Node* p;
	p = head->next;
	cout << " " << setw(2) << p->a << setw(2) << "出队" << endl;
	head->next = p->next;
	delete p;
	head->a--;
}

template<class T>//类模板
int Queue::getlength()
{
	return head->a;
}

template<class T>//类模板
void Queue::print()
{
	Node* p;
	p = head->next;
	cout << "队列中的函数元素是:" << endl;
	while (p)
	{
		cout << p->a << "->";
		p = p->next;

	}
}

template<class T>//类模板
Queue::Queue()
{
	rear = head = new Node();
}

 数据结构:队列---顺序队列

1.先进先出(FIFO)或 后进后出(LTLO)

2.队首、队尾

3.队列的操作

  • Push
  • Pop
  • Front
  • Rear
  • IsEmpty

     

 h文件 加了保护的ifdef 调用时报错 去掉就正常

//#ifdef _顺序队列_H
//
//#define _顺序队列_H
#include<iostream>


using namespace std;//copy要用
template<class T>
class Queue
{
public:
	Queue(int queueCapacity = 10);
	bool IsEmpty() const;
	T& Front()const;//查看 读取队首的数据
	T& Rear() const;//队尾下标
	void Push(const T& item);//队首插入
	void Pop();//队尾插入
private:
	T* queue;
	int front;//记录队首下标
	int rear;//队尾下标
	int capacity;
};

template<class T>
Queue<T>::Queue(int queueCapacity) :capacity(queueCapacity)
{
	if (capacity < 1)throw "Queue capacity must be>0";
	queue = new T[capacity];
	front = rear = 0;
}

template<class T>
inline bool Queue<T>::IsEmpty()const
{
	return front == rear;
}

template<class T>
void Queue<T>::Push(const T& item)
{
	/*if (rear == capacity - 1)
		rear = 0;
	else
	    rear++;*/
	if ((rear + 1) % capacity == front)//队列满了
	{
		//加倍
		T* newQueue = new T[2 * capacity];

		int start = (front + 1) % capacity;
		if (start < 2)//没有回绕 ,no wrap
			copy(queue + start, queue + start + capacity - 1, newQueue);
		else//wrap
		{
			copy(queue + start, queue + start + capacity, newQueue);
			copy(queue, queue + start + capacity + 1, newQueue + capacity - start);
		}

	//	if((rear+1)%capacity==front)
		front = 2 * capacity - 1;
		rear =capacity - 2;
		capacity *= 2;
		delete[] queue;
		queue = newQueue;

	}
	rear = (rear + 1) % capacity;//高水平!好
	queue[rear] = item;
}

template<class T>
inline T& Queue<T>::Front()const
{
	if (IsEmpty()) throw "Queue is empty.No front element";
	return queue[(front+1) % capacity];
}

template<class T>
inline T& Queue<T>::Rear()const
{
	if (IsEmpty()) throw "Queue is empty.No rear element";
	return queue[rear];
}

template<class T>
void Queue<T>::Pop()
{
	if (IsEmpty()) throw "Queue is empty.Cannot delete.";
	front = (front + 1) % capacity;
	queue[front].~T();
}
//#endif // _顺序队列
#include<iostream>
#include"顺序队列.h"

using namespace std;


int main()
{
	cout << "测试顺序队列" << endl;


	//Queue<int> q;
	Queue<char> q(5);

	q.Push('A');
	q.Push('B');
	q.Push('C');
	cout << q.Front() << "," << q.Rear() << endl;
	q.Push('D');
	q.Push('E');
	cout << q.Front() << "," << q.Rear() << endl;
	/*q.Pop();*/
	q.Push('F');
	cout << q.Front() << "," << q.Rear() << endl;
	q.Push('G');
	cout << q.Front() << "," << q.Rear() << endl;
	return 0;

}

 链式队列

1.用链表做的队列

2.先进先出

3.使用C++模板

#include<iostream>

using namespace std;

template<class Object>
class Queue
{
public:
	Queue();
	~Queue();

	bool isEmpty() const;
	const Object& getFront() const;
	void enqueue(const Object& x);
	Object dequeue();
	void makeEmpty();

private:
	struct ListNode
	{
		Object element;
		ListNode* next;

		ListNode(const Object& theElement, ListNode* n = 0)
			:element(theElement), next(n) {}
	};

	ListNode* front;
	ListNode* back;
};

template<class Object>
Queue<Object>::Queue()
{
	front = back = 0;
}

template<class Object>
Queue<Object>::~Queue()
{
	makeEmpty();
}

template<class Object>
void Queue<Object>::makeEmpty()
{
	while (!isEmpty())
	{
		dequeue();
	}
}

template<class Object>
bool Queue<Object>::isEmpty() const
{
	return front == 0;
}

template<class Object>
const Object & Queue<Object>::getFront() const
{
	if (isEmpty())
		throw "Queue is empty.";
	return front->element;
}

template<class Object>
void Queue<Object>::enqueue(const Object& x)
{
	if (isEmpty())
		back = front = new ListNode(x);
	else
		back = back->next = new ListNode(x);
}

template<class Object>
Object Queue<Object>::dequeue()
{
	Object frontItem = getFront();

	ListNode* old = front;
	front = front->next;

	delete old;
	return frontItem;
}

 

#include<iostream>
#include"链式队列.h"

int main()
{
	cout << "链式队列:" << endl;
	Queue<int>myQ;

	myQ.enqueue(10);
	myQ.enqueue(20);
	myQ.enqueue(30);

	cout << myQ.getFront() << endl;
	myQ.dequeue();
	//cout << myQ.getFront() << endl;
	cout << myQ.dequeue() << endl;
	cout << myQ.dequeue() << endl;

	for (int j = 0;j < 8;j++)
	{
		for (int i = 0;i < 8;i++)
			myQ.enqueue(i);

		while (!myQ.isEmpty())
			cout << myQ.dequeue() << endl;
	}
	return 0;
}

 函数模板

1.函数模板\rightarrow实例化\rightarrow函数

2.模板形参

template<typename  T>

template<class T>

3.四个例子 

#include<iostream>
#include<string>
#include<fstream>
#include<sstream>
using namespace std;
//
//int compare(const double& v1, const double& v2)
//{
//	if (v1 < v2) return -1;
//	if (v1 > v2)return 1;
//	return 0;
//}
//
//int compare(const string& v1, const string& v2)
//{
//	if (v1 < v2) return -1;
//	if (v1 > v2)return 1;
//	return 0;
//}

//函数模板
template<typename T>
int compare(const T& v1, const T& v2)
{
		if (v1 < v2) return -1;
		if (v1 > v2)return 1;
		return 0;
}

template<class T>
T absVal(T val)
{
	return val > 0 ? val : -val;
}

template<typename T1,typename T2>
T1& print(T1& s, T2 val)
{
	s << val;
	return s;
}

template<class T>
const 
T & bigger(const T& v1,const T & v2)
{
	return v1 > v2 ? v1 : v2;
}
int main()
{
	double dval = -0.8978;
	float fval = -12.3;
	string oristr = "this is a test";
	string desstr;
	ostringstream oss(desstr);
	ofstream outFile("result.dat");

	print(cout, -3) << endl;
	print(cout, dval) << endl;
	print(cout, fval) << endl;
	print(cout, oristr) << endl;

	print(outFile, -3) << endl;
	print(outFile, dval) << endl;
	print(outFile, fval) << endl;
	print(outFile, oristr) << endl;

	outFile.close();
	print(oss, -3) << endl;
	print(oss, dval) << endl;
	print(oss, fval) << endl;
	print(oss, oristr) << endl;

	cout << oss.str() << endl;

	double d1 = 1.23;
	double d2 = 9.56;
	
	cout << compare(d1, d2) << endl;

	string s1("hi");
	string s2("world");
	cout << compare(s1, s2) << endl;

	

	cout << absVal(dval) << endl;
	cout << absVal(fval) << endl;

	cout << bigger(s1, s2) << endl;
	cout << bigger(d1,d2) << endl;
	system("pause");
	return 0;
}

 异常

1.传统的处理方法

2.现代的处理方法:处理异常

try

catch

throw

异常类型

  • 数字
  • 字符串
  • 类对象

 

下面是传统处理fopen 和outopen有问题

 

#include<iostream>
#include<stdio.h>

int my_cp(const char* src_file, const char* dest_file)
{
	FILE* in_file, * out_file;

	in_file = fopen(src_file, "rb");
	if (in_file == NULL)
	{
		return 1;
	}
	
	out_file = fopen(dest_file, "wb");
	if (out_file == NULL)
	{
		return 2;
	}

	char rec[256];
	size_t bytes_in, bytes_out;
	while ((bytes_in=fread(rec,1,256,in_file))>0)
	{
		bytes_out = fwrite(rec, 1, bytes_in, out_file);
		if (bytes_in != bytes_out)
		{
			return 3;
		}

	}
	fclose(in_file);
	fclose(out_file);
	return 0;
}
int main()
{
	int result;
	result = my_cp("d:\\temp\\1.txt", "\\temp\\2.txt");//自己找到1.txt和2.txt文件的地址
//如d盘 temp文件夹下的1.txt和2.txt
	printf("OK!\n");
	return 0;
}

现代的处理方法: 

#include<iostream>
#include<stdio.h>

class BadSrcFile {};
class BadDestFile {};
class BadCopy {};

int my_cp(const char* src_file, const char* dest_file)
{
	FILE* in_file, * out_file;

	in_file = fopen(src_file, "rb");
	if (in_file == NULL)
	{
		return 1;
	}
	
	out_file = fopen(dest_file, "wb");
	if (out_file == NULL)
	{
		return 2;
	}

	char rec[256];
	size_t bytes_in, bytes_out;
	while ((bytes_in=fread(rec,1,256,in_file))>0)
	{
		bytes_out = fwrite(rec, 1, bytes_in, out_file);
		if (bytes_in != bytes_out)
		{
			return 3;
		}

	}
	fclose(in_file);
	fclose(out_file);
	return 0;
}

void  my_cp2(const char* src_file, const char* dest_file)
{
	FILE* in_file, * out_file;

	in_file = fopen(src_file, "rb");
	if (in_file == NULL)
	{
		//	return 1;
		throw 1;//throw就是抛出异常
		//throw"打开源文件时出错!";
	}

	out_file = fopen(dest_file, "wb");
	if (out_file == NULL)
	{
		//return 2;
	throw 2;	
	
	//throw "打开目标文件时出错!";
	}

	char rec[256];
	size_t bytes_in, bytes_out;
	while ((bytes_in = fread(rec, 1, 256, in_file)) > 0)
	{
		bytes_out = fwrite(rec, 1, bytes_in, out_file);
		if (bytes_in != bytes_out)
		{
			//return 3;
			throw 3;
			//throw "拷贝文件出错!";
		}

	}
	fclose(in_file);
	fclose(out_file);
	//return 0;
}

void  my_cp3(const char* src_file, const char* dest_file)
{
	FILE* in_file, * out_file;

	in_file = fopen(src_file, "rb");
	if (in_file == NULL)
	{
		//	return 1;
		//throw 1;//throw就是抛出异常
		throw"打开源文件时出错!";
	}

	out_file = fopen(dest_file, "wb");
	if (out_file == NULL)
	{
		//return 2;
	//	throw 2;
		throw "打开目标文件时出错!";
	}

	char rec[256];
	size_t bytes_in, bytes_out;
	while ((bytes_in = fread(rec, 1, 256, in_file)) > 0)
	{
		bytes_out = fwrite(rec, 1, bytes_in, out_file);
		if (bytes_in != bytes_out)
		{
			//return 3;
			//throw 3;
			throw "拷贝文件出错!";
		}

	}
	fclose(in_file);
	fclose(out_file);
	//return 0;
}

void  my_cp4(const char* src_file, const char* dest_file)
{
	FILE* in_file, * out_file;

	in_file = fopen(src_file, "rb");
	if (in_file == NULL)
	{
		//	return 1;
		//throw 1;//throw就是抛出异常
		//throw"打开源文件时出错!";
		throw BadSrcFile();
	}

	out_file = fopen(dest_file, "wb");
	if (out_file == NULL)
	{
		//return 2;
	//	throw 2;
		//throw "打开目标文件时出错!";
		throw BadDestFile();
	}

	char rec[256];
	size_t bytes_in, bytes_out;
	while ((bytes_in = fread(rec, 1, 256, in_file)) > 0)
	{
		bytes_out = fwrite(rec, 1, bytes_in, out_file);
		if (bytes_in != bytes_out)
		{
			//return 3;
			//throw 3;
		//	throw "拷贝文件出错!";
			throw BadCopy();
		}

	}
	fclose(in_file);
	fclose(out_file);
	//return 0;
}
int main()
{
	int result;
	if ((result = my_cp("c:\\OPP二\\1.txt", "\\OPP二\\2.txt")) != 0)
	{
		switch (result)
		{
		case 1:
			printf("打开源文件时出错!\n");
			break;
		case 2:
			printf("打开目标文件时出错!\n");
			break;
		case 3:
			printf("拷贝文件时出错!\n");
			break;
		default:
			break;
		}
	}
	try
	{
		my_cp2("c:\\OPP二\\1.txt", "\\OPP二\\2.txt");
		my_cp3("c:\\OPP二\\1.txt", "\\OPP二\\2.txt");
		my_cp4("c:\\OPP二\\1.txt", "\\OPP二\\2.txt");
	}
	catch (const char* e)
	{
		printf("%s\n", e);
	}

	catch (BadSrcFile e)
	{
		printf("发生异常:打开源文件时出错!\n");
	}
	catch (BadDestFile e)
	{
		printf("发生异常:打开目标文件时出错!\n");
	}
	catch (BadCopy e)
	{
		printf("发生异常:拷贝时出错!\n");
	}
	catch (...)
	{
		printf("发生了未知异常!\n");
	}
	printf("OK!\n");
	return 0;
}

异常层次结构

1.异常是类---创建自己的异常类

2.异常派生

3.异常中的数据:数据成员 

4.按引用传递异常

  • 在异常中使用虚函数 
#include<iostream>

using namespace std;

const int DefaultSize = 10;


//动态数组
class Array
{
public:
	Array(int itsSize = DefaultSize);
	~Array() { delete[] pType; }

	//运算符重载
	int& operator[](int offSet);
	const int& operator[](int offSet)const;

	//访问器 ,accrssors
	int GetitsSize()const { return itsSize; }
	
	//异常类
	class xBoundary {};
	class xSize 
	{
	public:
		xSize() {}
		xSize(int size) : itsSize(size) {}
		~xSize() {}
		int GetSize() { return itsSize; } 
		virtual void PrintError()
		{
			cout << "下标发生错误:" << itsSize << endl;
		}

	protected:
		int itsSize;
	};
	class xZero : public xSize
	{
	public:
		xZero(int size) : xSize(size) {}
		virtual void PrintError()
		{
			cout << "下标不能是0:" << itsSize << endl;
		}
	};
	class xNegative : public xSize 
	{
	public:
		xNegative(int size) : xSize(size) {}
		virtual void PrintError()
		{
			cout << "下标不能为负数:" << itsSize << endl;
		}
	};
	class xTooSmall : public xSize
	{
	public:
		xTooSmall(int size) : xSize(size) {}
		virtual void PrintError()
		{
			cout << "下标不能小于10:" << itsSize << endl;
		}
	};
	
	class xTooBig : public xSize
	{
	public:
		xTooBig(int size) : xSize(size) {}
		virtual void PrintError()
		{
			cout << "下标不能大于3000:" << itsSize << endl;
		}
	};
private:
	int* pType;
	int itsSize;
};

int &Array::operator[](int offSet)
{
	int size = this->GetitsSize();
	if (offSet >= 0 && offSet < size)
		return pType[offSet];
	throw xBoundary();
}

const int &Array::operator[](int offSet)const
{
	int size = this->GetitsSize();
	if (offSet >= 0 && offSet < size)
		return pType[offSet];
	throw xBoundary();
}
Array::Array(int size) :itsSize(size)
 {
	if (size == 0)
		throw xZero(size);
	else if (size < 0)
		throw xNegative(size);
	else if (size > 30000)
		throw xTooBig(size);
	else if (size <10)
		throw  xTooSmall(size);

	pType = new int[size];
	for (int i = 0;i < size;i++)
		pType[i] = 0;//初始化 为0
}
int main()
{
	Array a;
	Array b(12);

	Array intArray(20);

	try
	{
	/*	b[6] = 88;
		b[22] = 99;
		cout << b[6] << endl;
		cout << "测试一下" << endl;*/
		//Array b(22);

		Array b(7);

		for (int j = 0;j < 100;j++)
		{
			intArray[j] = j;
			cout << "intArray[" << j << "]okay..." << endl;
		}
			
	}
	//虚函数 多态
	catch (Array::xSize& exp)
	{
		exp.PrintError();
	}
	catch (Array::xBoundary )
	{
		cout << "下标越界了!" << endl;
	}
	/*catch (Array::xZero theException)
	{
		cout << "下标不能为0" << theException.GetSize() << endl;
	}
	catch (Array::xNegative theException)
	{
		cout << "下标不能是负数!" << theException .GetSize()<< endl;
	}
	catch (Array::xTooBig theException)
	{
		cout << "下标不能大于30000!" << theException.GetSize() << endl;
	}
	catch (Array::xTooSmall theException)
	{
		cout << "下标不能小于10!" << theException.GetSize() << endl;
	}*/
	catch (...)
	{
		cout << "发生未知异常!" << endl;
	}


	cout << "Done!" << endl;
	return 0;
}

 标准异常

  • exception
  • runtime_error
  • rang_error
  • overflow_error
  • underflow_error
  • logic_error
  • domain_error
  • invalid_argument
  • length_error
  • out_of_range

 

#include<iostream>
#include<new>
using namespace std;

class Dog
{
public:
	Dog()
	{
		parr = new int[1000000];//4MB
	}
private:
	int* parr;

};
int main()
{
	Dog* pDog;

	try
	{
		for (int i = 1;i < 1000;i++)//4GB!
		{
			pDog = new Dog();
			cout << i << ":new Dog 成功" << endl;
		}
	}
	catch (bad_alloc err)
	{
		cout << "new Dog 失败:" << err.what() << endl;
	}
	return 0;
}
#include<iostream>
#include<bitset>//容器 抛出异常
#include<string>

using namespace std;
int main()
{
	try 
	{
		/*string s("101ab0110010");*///ab的原因
		string s("1010110010");
		bitset<10>b(s);
		cout << "bitset ok" << endl;
	}
	catch (invalid_argument err)
	{
		cout << "bitset error:" << err.what() << endl;
	}
	return 0;
}
#include<iostream>


using namespace std;

class 学生
{
public:
	学生(int 年龄)
	{
		if (年龄 < 0 || 年龄 >150)
			throw out_of_range("年龄不能小于0或大于150");
		this->m_年龄 = 年龄;
	}
private:
	int m_年龄;
};

int main()
{
	try
	{
		学生 张飞(200);
		cout << "学生没错" << endl;
	}
	catch (out_of_range err)
	{
		cout << "学生出错:" << err.what() << endl;
	}
	return 0;
}
#pragma once
#include<iostream>
//
//#ifdef STACK_H
//#define STACK_H

#include<deque>
#include<exception>

template<class T>
class Stack
{
protected:
	std::deque<T> c;
public:
	class ReadEmptyStack : public std::exception//继承
	{
	public:
		virtual const char* what()const throw()
		{
			return "read empty stack 堆栈是空的";
		}
	};

	bool empty()const
	{
		return c.empty();
	}
	void push(const T& elem)
	{
		c.push_back(elem);
	}
	T pop()
	{
		if (c.empty())
		{
			throw ReadEmptyStack();
		}
		T elem(c.back());
		c.pop_back();
		return elem;
	}
	T& top()
	{
		if (c.empty())
		{
			throw ReadEmptyStack();
		}
		return c.back();
	}
};

//#endif // STACK_H
#include<iostream>
#include"标准异常4.h"

using namespace std;

int main()
{
	try
	{
		Stack<int> st;
		st.push(1);
		st.push(2);
		st.push(3);
		cout << "pop:"<<st.pop() << endl;
		cout << "top:"<<st.top() << endl;
		cout << "pop:" << st.pop() << endl;
		cout << "top:" << st.top() << endl;
		cout << "pop:" << st.pop() << endl;
		cout << "top:" << st.top() << endl;
		cout << "pop:" << st.pop() << endl;
	}
	catch (const exception& e)
	{
		cerr << "发生异常" << e.what() << endl;
	}
	cout << "hello Stack" << endl;
	return 0;
}

智能指针、auto_ptr类

1.常规指针--容易产生内存泄漏

2.智能指针

  • 自己动手设计智能指针--很难! 

深度复制、写时复制、引用计数、引用连接、破坏性复制 

  • 使用std::auto_ptr智能指针
  • 使用Boost智能指针
  • 使用ATL框架中的智能指针----如CComPtr,CComQIPtr等等. 
#include<iostream>
#include<memory>
//#include"智能指针.h"

class Dog 
{
	//省略
};

void demo2()
{
	std::auto_ptr<double> pd(new double);
	*pd = 28.5;

	std::auto_ptr<Dog> pDog(new Dog());

	std::cout << *pd << std::endl;
}
void demo1()
{
	double d;
	d = 25.5;

	double* pd = new double;
	*pd = 25.5;

	Dog* pDog = new Dog();
	//做什么工作
	std::cout << d << std::endl;

	//if (xxx)
	//	throw exception();
	delete pDog;
		delete pd;
	return;
}

int main()
{
	demo1();
	demo2();
	return 0;
}

 命名空间

1.命令空间的定义

每个命名空间是一个作用域

命名空间可以是不连续的

接口和实现的分离

嵌套命名空间

2.命名空间成员的使用

using std :: vector;

using primer = cplusplus_primer;

using namespace std;

#ifndef _BS_H
#define _BS_H

#include<string>

//using namespace std;//不能
//using srd::string;不能

class Book
{

};
namespace Bookstore
{
	class Dog
	{};
	class Sales_item
	{
	public:
		Sales_item(const std::string& book = " ") : isbn(book), units_sold(0), revenue(0.0) {}

		double avg_price() const;
	private:
		std::string isbn;
		unsigned units_sold;
		double revenue;
	};

	double Sales_item::avg_price() const
	{
		if (units_sold)
			return revenue / units_sold;
		else
			return 0;
	}
}

namespace MyApp
{
	class Cat
	{};
}

#endif

 

#include<iostream>
#include"命名空间.h"

//using namespace std;
using std::cout;
using std::endl;
//using namespace Bookstore;
using Bookstore::Sales_item;

namespace bs = Bookstore;//别名

class Ant
{

};
namespace MyApp
{
	double pail;
	void processTrans()
	{
		Bookstore::Sales_item s;
		bs::Sales_item s2;
	}
	class Dog 
	{};

	namespace Lib
	{
		class Query
		{};
	}
}
int main()
{
	using namespace MyApp;

	cout << "hello" << endl;
	MyApp::processTrans();
	MyApp::Dog dog;
	MyApp::Cat cat;

	/*Bookstore::Sales_item item;*/
	Sales_item item;

	Bookstore::Dog d1;
	//bs::Dog d1;//可以用别名
	MyApp::Dog d2;

	MyApp::Lib::Query q;

	::Ant ant;//全局的 ::前面不用加空间
	system("pause");
	return 0;
}

多继承与虚基类

1.多继承

2.多继承中的二义性问题

3.虚基类

4.虚基类的构造函数

 

#include<iostream>

using std::cout;
using std::endl;

enum COLOR {Red,Green,Blue,Yellow,White,Black,Brown};

class Animal
{
public:
	Animal(int);
	virtual ~Animal(){ cout << "Animal 析构函数被调用...\n"; }
	virtual int GetAge() { return itsAge;}
	virtual void SetAge(int age) { itsAge = age; }
	
private:
	int itsAge;

};

Animal::Animal(int age) : itsAge(age)
{
	cout << "Animal的构造函数被调用...\n";
}

class Horse : virtual public Animal
{
public:
	Horse(COLOR color,int height,int age);
	virtual ~Horse() { cout << "Horse 析构函数被调用...\n"; }
	virtual void Whinny()const { cout << "Whinny!...";}
	virtual int GetHeight() const { return itsHeight; }

private:
	int itsHeight;
	COLOR itsColor;
};


Horse::Horse(COLOR color, int height,int age) : Animal(age), itsColor(color),itsHeight(height)
{
	cout << "Horse析构函数被调用...\n";
}
class Bird : virtual public Animal
{
public:
	Bird(COLOR color,bool migrates,int age);
	virtual ~Bird() { cout << "Bird 析构函数被调用...\n"; }

	//              鸟叫
	virtual void Chirp() const { cout << "Chirp..."; }
	virtual void Fly() const
	{
		cout << "I can fly! I can fly ! ";
	}
	virtual bool GetMigration() const { return itsMigration; }
	virtual COLOR GetColor()const { return itsColor; }
private:
	bool itsMigration;
	COLOR itsColor;
};

Bird::Bird(COLOR color,bool migrates,int age) : Animal(age), itsColor(color),itsMigration(migrates)
{
	cout << "Bird 构造函数被调用...\n";
}

class Pegasus : public Horse, public Bird
{
public:
	void Chirp() const{ Whinny(); }
	Pegasus(COLOR,int, bool, long,int);
	~Pegasus(){cout <<"Pefasus析构函数被调用...\n";}
	virtual long GetNumberBelievers()const
	{
		return itsNumberBelievers;
	}
private:
	long itsNumberBelievers;
};

Pegasus::Pegasus(COLOR aColor,int height, bool migrates, long numBelieve,int age)
	: Horse(aColor,height,age),
	Bird(aColor,migrates,age), 
	itsNumberBelievers(numBelieve),
	Animal(age)
{
	cout << "Pegasus构造函数被调用...\n";
}
int main()
{
	Pegasus* pPeg = new Pegasus(Red,5, true, 10,2);
	pPeg->Fly();
	pPeg->Chirp();
	pPeg->Whinny();
	cout << "有" << pPeg->GetNumberBelievers() << "人相信世界上有飞马。" << endl;

	pPeg->Bird::GetColor();
	COLOR color = pPeg->Bird::GetColor();
	cout << "飞马的颜色:" << color << endl;
	
	/*pPeg->Horse::GetAge();*/
	pPeg->GetAge();//继承不明确 用virtual 虚函数解决

	delete pPeg;
	return 0;
}

特殊工具与技术

allocator类(内存分配)

RTTI

类成员的指针

嵌套类

union

局部类

位域

volatile(不稳定,不用优化)

extern"C"(调用C的函数,比较常用,前面的都不常用)

//这是调用的C代码
#include<stdio.h>

void show(char* msg)
{
	printf("%s\n", msg);
}
#include<iostream>

using namespace std;

class Item_base//基类
{
public:
	virtual double net_price(size_t n)const
	{
		class Cat//内部类 在函数内部使用
		{

		};
		Cat cat;
		return  n * price;
	}

	class Dog
	{

	};
public:
	std::string isbn;
protected:
	double price;
};
class Bulk_item : public Item_base//继承类
{
public:
	double net_price(std::size_t cnt) const//改写
	{
		if (cnt > min_qty)
			return cnt * (1 - discount) * price;
		else
			return cnt * price;
	}
private:
	std::size_t min_qty;
	double discount;
};

union TokenValue
{
	char cval;
	int ival;
	double dval;
};

typedef unsigned int Bit;

class File
{
public:
	Bit mode : 2;
	Bit modified : 1;
	Bit prot_owner : 3;
	Bit prot_group : 3;
	Bit prot_world : 3;
	//...

};

enum {READ=01,WRITE=02};

extern "C" void show(char*);
int main()
{

	//show("hello extern \"C\"\n");出了问题
	File myFlie;
	myFlie.mode = WRITE;
	myFlie.modified = 1;

	int x;
	volatile int y;


	TokenValue myToken = { 'a' };
	cout << myToken.ival << endl;

	Item_base* pItem = new Item_base();

	allocator<Item_base>a;
	a.allocate(100);

	Item_base* bp = new Item_base();
	Bulk_item* dp = new Bulk_item();
	
	Item_base* bp2 = dp;
	Bulk_item* dp2 = dynamic_cast<Bulk_item*>(bp);//RTTI

	if (typeid(Bulk_item) == typeid(*dp))cout << "Bulk_item类型" << endl;
	cout << typeid(*bp).name() << endl;
	cout << typeid(*dp).name() << endl;

	std::string	Item_base::* p = &Item_base::isbn;
	double(Item_base:: * pmf)(std::size_t) const = &Item_base::net_price;


	system("pause");
	return 0;
}

 

OPP(Object Push Profile)是一种无线通信协议,主要用于在蓝牙技术中实现设备之间的物体传输。OPP协议基于传统的客户端/服务器模型,并支持设备之间的对象传送。 在OPP协议中,发送方设备被称为客户端,接收方设备被称为服务器。客户端可以向服务器发送请求,请求传输特定的对象。服务器可以接受请求并根据请求来发送对象。对象可以是文件、联系人、图片等等。 OPP协议使用了OBEX(Object Exchange)协议作为其基础协议。 OBEX协议是一种用于无线设备之间对象交换的协议,它提供了一个通用的框架,使得不同设备之间可以方便地交换数据。OBEX协议支持基于客户端/服务器的通信模型,支持连接管理、对象传输和会话管理等功能。 OPP协议使用OBEX协议在蓝牙通信链路中进行对象的传输。当一个设备想要传输一个对象给另一个设备时,它首先会建立蓝牙连接,然后使用OPP协议发送一个请求,请求服务器传输该对象。服务器收到请求后,会根据请求的内容将对象传输给客户端。 OPP协议在实际中被广泛应用于各种蓝牙设备之间的数据传输。例如,手机之间可以使用OPP协议传输文件、图片和联系人信息,蓝牙耳机可以使用OPP协议接收音频文件等。通过使用OPP协议,不同设备间的数据交换和共享变得更加简单和高效。 总之,OPP是一种使用OBEX作为基础协议的无线通信协议,用于在蓝牙设备之间实现对象的传输。其主要应用于各种蓝牙设备之间的数据交换,提供了一种简单、方便和高效的方式来共享和传输对象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值