**管理指针成员**
三种方法
- 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.派生类基类
引用转换/指针转换 ( 没问题 动态绑定 多态)
对象转换(有问题)
2.基类派生类
基类到派生类的自动转换不存在
强制转换
#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.函数模板实例化
函数
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;
}