1. 一些基础的规则
- 类中对于不会改变数据的函数,在后面加上const(常量成员函数)—— 方便常量对象的调用。
- 一般没有指针的类不需要析构函数。
- 同一个类的各个对象之间互为友元。
- 参数和返回值尽量采用引用。
- 数据中有指针的类必须要重写拷贝构造和拷贝赋值等,如果一个类需要自定义析构函数,那么可以肯定它也需要定义拷贝赋值运算符和拷贝构造函数。
- 静态成员函数用于处理静态数据。
- 基类的析构函数要写成virtual。
2. 日期类
2.1 日期类头文件
#ifndef DATE_H
#define DATE_H
#ifndef _MSC_VER
#define NOEXCEPT noexcept
#else
#define NOEXCEPT
#endif
#include <iostream>
#include <vector>
class Date {
friend bool operator ==(const Date& lhs, const Date& rhs);
friend bool check(const Date &d);
friend std::ostream& operator <<(std::ostream& os, const Date& d);
public:
typedef std::size_t Size;
Date() = default;
explicit Date(Size days);
Date(Size d, Size m, Size y) : day(d), month(m), year(y) {}
Date(std::istream &is, std::ostream &os);
Date(const Date& d);
Date(Date&& d) NOEXCEPT;
Date& operator= (const Date& d);
Date& operator= (Date&& rhs) NOEXCEPT;
~Date() { std::cout << "destroying\n"; }
Size toDays() const;
Date& operator +=(Size offset);
Date& operator -=(Size offset);
private:
Size day = 1;
Size month = 1;
Size year = 0;
};
static const Date::Size YtoD_400 = 146097;
static const Date::Size YtoD_100 = 36524;
static const Date::Size YtoD_4 = 1461;
static const Date::Size YtoD_1 = 365;
static const std::vector<Date::Size> monthsVec_n =
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
static const std::vector<Date::Size> monthsVec_l =
{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
std::ostream& operator <<(std::ostream& os, const Date& d);
std::istream& operator >>(std::istream& is, Date& d);
int operator - (const Date& lhs, const Date& rhs);
bool operator ==(const Date& lhs, const Date& rhs);
bool operator !=(const Date& lhs, const Date& rhs);
bool operator < (const Date& lhs, const Date& rhs);
bool operator <=(const Date& lhs, const Date& rhs);
bool operator >(const Date& lhs, const Date& rhs);
bool operator >=(const Date& lhs, const Date& rhs);
Date operator - (const Date& lhs, Date::Size rhs);
Date operator +(const Date& lhs, Date::Size rhs);
bool check(const Date &d);
bool isLeapYear(Date::Size y);
inline
bool check(const Date &d)
{
if (d.month == 0 || d.month > 12)
return false;
else
{
if (d.month == 1 || d.month == 3 || d.month == 5 || d.month == 7 ||
d.month == 8 || d.month == 10 || d.month == 12)
{
if (d.day == 0 || d.day > 31) return false;
else
return true;
}
else
{
if (d.month == 4 || d.month == 6 || d.month == 9 || d.month == 11)
{
if (d.day == 0 || d.day > 30) return false;
else
return true;
}
else
{
if (isLeapYear(d.year))
{
if (d.day == 0 || d.day > 29) return false;
else
return true;
}
else
{
if (d.day == 0 || d.day > 28) return false;
else
return true;
}
}
}
}
}
inline
bool isLeapYear(Date::Size y)
{
if (!(y % 400))
{
return true;
}
else
{
if (!(y % 100))
{
return false;
}
else
return !(y % 4);
}
}
#endif
2.2 日期类执行文件
#include "Data.h"
#include <algorithm>
Date::Date(Size days)
{
Size y400 = days / YtoD_400;
Size y100 = (days - y400 * YtoD_400) / YtoD_100;
Size y4 = (days - y400 * YtoD_400 - y100 * YtoD_100) / YtoD_4;
Size y = (days - y400 * YtoD_400 - y100 * YtoD_100 - y4 * YtoD_4) / 365;
Size d = days - y400 * YtoD_400 - y100 * YtoD_100 - y4 * YtoD_4 - y * 365;
this->year = y400 * 400 + y100 * 100 + y4 * 4 + y;
std::vector<Size>currYear
= isLeapYear(this->year) ? monthsVec_l : monthsVec_n;
Size D_accumu = 0, M_accumu = 0;
std::find_if(currYear.cbegin(), currYear.cend(), [&](Size m)
{
D_accumu += m;
M_accumu++;
if (d < D_accumu)
{
this->month = M_accumu;
this->day = d + m - D_accumu;
return true;
}
else
return false;
});
}
Date::Date(std::istream &is, std::ostream &os)
{
is >> day >> month >> year;
if (is)
{
if (check(*this)) return;
else
{
os << "Invalid input! Object is default initialized.";
*this = Date();
}
}
else
{
os << "Invalid input! Object is default initialized.";
*this = Date();
}
}
Date::Date(const Date &d) :
day(d.day), month(d.month), year(d.year)
{}
Date::Date(Date&& d) NOEXCEPT :
day(d.day), month(d.month), year(d.year)
{
std::cout << "copy moving";
}
Date &Date::operator= (const Date &d)
{
this->day = d.day;
this->month = d.month;
this->year = d.year;
return *this;
}
Date &Date::operator =(Date&& rhs) NOEXCEPT
{
if (this != &rhs)
{
this->day = rhs.day;
this->month = rhs.month;
this->year = rhs.year;
}
std::cout << "moving =";
return *this;
}
Date::Size Date::toDays() const
{
Size result = this->day;
std::vector<Size>currYear
= isLeapYear(this->year) ? monthsVec_l : monthsVec_n;
for (auto it = currYear.cbegin(); it != currYear.cbegin() + this->month - 1; ++it)
result += *it;
result += (this->year / 400) * YtoD_400;
result += (this->year % 400 / 100) * YtoD_100;
result += (this->year % 100 / 4) * YtoD_4;
result += (this->year % 4) * YtoD_1;
return result;
}
Date &Date::operator +=(Date::Size offset)
{
*this = Date(this->toDays() + offset);
return *this;
}
Date &Date::operator -=(Date::Size offset)
{
if (this->toDays() > offset)
*this = Date(this->toDays() - offset);
else
*this = Date();
return *this;
}
std::ostream&
operator <<(std::ostream& os, const Date& d)
{
os << d.day << " " << d.month << " " << d.year;
return os;
}
std::istream&
operator >>(std::istream& is, Date& d)
{
if (is)
{
Date input = Date(is, std::cout);
if (check(input)) d = input;
}
return is;
}
int operator -(const Date &lhs, const Date &rhs)
{
return lhs.toDays() - rhs.toDays();
}
bool operator ==(const Date &lhs, const Date &rhs)
{
return (lhs.day == rhs.day) &&
(lhs.month == rhs.month) &&
(lhs.year == rhs.year);
}
bool operator !=(const Date &lhs, const Date &rhs)
{
return !(lhs == rhs);
}
bool operator < (const Date &lhs, const Date &rhs)
{
return lhs.toDays() < rhs.toDays();
}
bool operator <=(const Date &lhs, const Date &rhs)
{
return (lhs < rhs) || (lhs == rhs);
}
bool operator >(const Date &lhs, const Date &rhs)
{
return !(lhs <= rhs);
}
bool operator >=(const Date &lhs, const Date &rhs)
{
return !(lhs < rhs);
}
Date operator - (const Date &lhs, Date::Size rhs)
{
Date result(lhs);
result -= rhs;
return result;
}
Date operator + (const Date &lhs, Date::Size rhs)
{
Date result(lhs);
result += rhs;
return result;
}
3. 书籍销售类
3.1 书籍销售类头文件
#ifndef SALE_DATA_H
#define SALE_DATA_H
#include<iostream>
#include<string>
using std::ostream;
using std::istream;
using std::string;
class Sales_data
{
friend istream& operator>>(istream&, Sales_data&);
friend ostream& operator<<(ostream&, const Sales_data&);
friend Sales_data operator+(const Sales_data&, const Sales_data&);
friend bool operator==(const Sales_data&, const Sales_data&);
friend bool operator!=(const Sales_data&, const Sales_data&);
public:
Sales_data() = default;
Sales_data(const string &s, unsigned n, double p) :
bookNo(s), unit_sold(n), revenue(p*n) { }
Sales_data(const Sales_data &orig) :
bookNo(orig.bookNo), unit_sold(orig.unit_sold), revenue(orig.revenue) { }
Sales_data(const string &s) :bookNo(s) { }
Sales_data(std::istream &is);
string const& isbn() const { return this->bookNo; }
Sales_data& operator+=(const Sales_data&);
Sales_data& operator=(const std::string&);
explicit operator std::string() const { return bookNo; }
explicit operator double() const { return avg_price(); }
private:
double avg_price() const;
string bookNo;
unsigned unit_sold = 0;
double revenue = 0.0;
};
inline
double Sales_data::avg_price() const {
if (unit_sold)
return revenue / unit_sold;
else
return 0;
}
inline
Sales_data& Sales_data::operator+=(const Sales_data &rhs) {
unit_sold += rhs.unit_sold;
revenue += rhs.revenue;
return *this;
}
#endif
3.2 书籍销售类执行文件
#include "Sales_data.h"
Sales_data::Sales_data(istream &is) {
is >> *this
}
std::istream& operator>>(std::istream &is, Sales_data &item)
{
double price = 0.0;
is >> item.bookNo >> item.unit_sold >> price;
if (is)
item.revenue = price * item.unit_sold;
else
item = Sales_data();
return is;
}
std::ostream& operator<<(std::ostream &os, const Sales_data &item)
{
os << item.isbn() << " " << item.unit_sold << " " << item.revenue << " " << item.avg_price();
return os;
}
Sales_data operator+(const Sales_data &lhs, const Sales_data &rhs)
{
Sales_data sum = lhs;
sum += rhs;
return sum;
}
bool operator==(const Sales_data &lhs, const Sales_data &rhs) {
return lhs.isbn() == rhs.isbn() &&
lhs.unit_sold == rhs.unit_sold &&
lhs.revenue == rhs.revenue;
}
bool operator!=(const Sales_data &lhs, const Sales_data &rhs) {
return !(lhs == rhs);
}
Sales_data& Sales_data::operator=(const std::string &isbn)
{
*this = Sales_data(isbn);
return *this;
}
4. 指针类
4.1 指针类1头文件
#ifndef MYHASPTR
#define MYHASPTR
#include <iostream>
#include <string>
using std::string;
using std::ostream;
class HasPtr {
friend bool operator<(const HasPtr&, const HasPtr&);
friend ostream& print(ostream &os, const HasPtr &hp);
friend void swap(HasPtr &hp1, HasPtr &hp2);
public:
HasPtr(const string &s = std::string()) :
ps(new string(s)), i(0) {
std::cout << "调用单参或无参构造函数" << std::endl;
}
HasPtr(const string &s, int t) :
ps(new string(s)), i(t) {
std::cout << "调用两参构造函数" << std::endl;
}
HasPtr(const HasPtr& hp) :
ps(new std::string(*hp.ps)), i(hp.i) {
std::cout << "调用拷贝构造函数" << std::endl;
}
HasPtr& operator=(const HasPtr &rhs_hp) {
std::cout << "调用赋值运算符" << std::endl;
if (this != &rhs_hp) {
string *temp_ps = new string(*rhs_hp.ps);
delete ps;
ps = temp_ps;
i = rhs_hp.i;
}
return *this;
}
~HasPtr() {
delete ps;
}
private:
std::string *ps;
int i;
};
inline
void swap(HasPtr &hp1, HasPtr &hp2) {
std::cout << "调用自定义版本的swap" << std::endl;
using std::swap;
swap(hp1.i, hp2.i);
swap(hp1.ps, hp2.ps);
}
inline
bool operator<(const HasPtr &lhs, const HasPtr &rhs) {
std::cout << "比较" << std::endl;
return *lhs.ps < *rhs.ps;
}
std::ostream& print(std::ostream &os, const HasPtr &hp)
{
os << "string:" << *hp.ps << " int:" << hp.i << std::endl;
return os;
}
#endif
4.2 指针类2头文件
class HasPtr {
friend ostream& print(ostream &os, const HasPtr &ps);
public:
HasPtr(const string &s = string()) :
ps(new string(s)), i(0), use(new std::size_t(1)) { }
HasPtr(std::size_t t, const std::string &s = std::string()) :
ps(new std::string(s)), i(t), use(new std::size_t(1)) { }
HasPtr(const HasPtr& hp) :
use(hp.use), ps(hp.ps), i(hp.i) {
++*use;
}
HasPtr& operator=(HasPtr &hp)
{
if (--*use == 0)
{
delete use;
delete ps;
}
ps = hp.ps;
use = hp.use;
i = hp.i;
++*hp.use;
return *this;
}
~HasPtr()
{
if (--*use == 0)
{
delete use;
delete ps;
}
}
private:
std::string *ps;
int i;
std::size_t *use;
};
std::ostream& print(std::ostream& os, const HasPtr &ps)
{
os << "string:" << *ps.ps << " int:" << ps.i << " use:" << *ps.use;
return os;
}
5. string类
5.1 string类1头文件
#ifndef MYSTRING
#define MYSTRING
#include<memory>
#include<iostream>
class String {
friend std::ostream& operator<<(std::ostream&, const String&);
public:
String() :
String("") {}
String(const char *);
String(const String&);
String& operator=(const String&);
~String();
const char *c_str() const { return elements; }
size_t size() const { return end - elements; }
size_t length() const { return end - elements - 1; }
private:
std::pair<char*, char*> alloc_n_copy(const char*, const char*);
void range_initializer(const char*, const char*);
void free();
private:
char *elements;
char *end;
std::allocator<char> alloc;
};
#endif
5.2 string类1执行文件
#include "String.h"
#include <algorithm>
std::pair<char*, char*>
String::alloc_n_copy(const char *b, const char *e)
{
auto str = alloc.allocate(e - b);
return{ str, std::uninitialized_copy(b, e, str) };
}
void String::range_initializer(const char *first, const char *last)
{
auto newstr = alloc_n_copy(first, last);
elements = newstr.first;
end = newstr.second;
}
String::String(const char *s)
{
char *sl = const_cast<char*>(s);
while (*sl)
++sl;
range_initializer(s, ++sl);
}
String::String(const String& rhs)
{
range_initializer(rhs.elements, rhs.end);
std::cout << "copy constructor" << std::endl;
}
void String::free()
{
if (elements)
{
std::for_each(elements, end, [this](char &c) { alloc.destroy(&c); });
alloc.deallocate(elements, end - elements);
}
}
String::~String()
{
free();
}
String& String::operator = (const String &rhs)
{
auto newstr = alloc_n_copy(rhs.elements, rhs.end);
free();
elements = newstr.first;
end = newstr.second;
std::cout << "copy-assignment" << std::endl;
return *this;
}
std::ostream& operator<<(std::ostream &os, const String &s)
{
char *c = const_cast<char*>(s.c_str());
while (*c)
os << *c++;
return os;
}
5.3 string类2头文件
5.4 string类2执行文件
6. Account类
6.1 Account类执行文件 —— 拥有静态成员
#include<iostream>
class Account {
public:
void calculate() { amount += amount * interestRate; }
static double rate() { return interestRate; }
static void rate(double newRate) { interestRate = newRate; }
private:
std::string owner;
double amount;
static double interestRate;
static constexpr double todayRate = 42.42;
static double initRate() { return todayRate; }
};
double Account::interestRate = initRate();
constexpr double Account::todayRate;
7. StrVec类
7.1 StrVec类头文件
#ifndef MYSTRVEC
#define MYSTRVEC
#include <memory>
#include <string>
#include <initializer_list>
using std::string;
using std::allocator;
using std::pair;
class StrVec {
friend bool operator==(const StrVec&, const StrVec&);
friend bool operator!=(const StrVec&, const StrVec&);
friend bool operator< (const StrVec&, const StrVec&);
friend bool operator> (const StrVec&, const StrVec&);
friend bool operator<=(const StrVec&, const StrVec&);
friend bool operator>=(const StrVec&, const StrVec&);
public:
StrVec():
elements(nullptr), first_free(nullptr), cap(nullptr) {}
StrVec(const StrVec&);
StrVec& operator=(const StrVec&);
StrVec(std::initializer_list<std::string>);
void range_initialize(const string *first, const string *last);
~StrVec();
StrVec& operator=(std::initializer_list<std::string>);
void push_back(const string&);
size_t size() const {
return first_free - elements;
}
size_t capacity() const {
return cap - first_free;
}
string* begin() const {
return elements;
}
string* end() const {
return first_free;
}
void reserve(size_t new_cap);
void resize(size_t count);
void resize(size_t count, const std::string&);
private:
pair<string*, string*> alloc_n_copy(const string*, const string*);
void free();
void chk_n_alloc() {
if (size() == capacity())
reallocate();
}
void reallocate();
void alloc_n_move(size_t new_cap);
private:
std::string *elements;
std::string *first_free;
std::string *cap;
allocator<string> alloc;
};
bool operator==(const StrVec&, const StrVec&);
bool operator!=(const StrVec&, const StrVec&);
bool operator< (const StrVec&, const StrVec&);
bool operator> (const StrVec&, const StrVec&);
bool operator<=(const StrVec&, const StrVec&);
bool operator>=(const StrVec&, const StrVec&);
#endif
7.2 StrVec类执行文件
#include "StrVec.h"
#include <algorithm>
StrVec::StrVec(const StrVec &rhs)
{
auto newdata = alloc_n_copy(rhs.begin(), rhs.end());
elements = newdata.first;
first_free = cap = newdata.second;
}
void StrVec::range_initialize(const std::string *first, const std::string *last)
{
auto newdata = alloc_n_copy(first, last);
elements = newdata.first;
first_free = cap = newdata.second;
}
StrVec::StrVec(std::initializer_list<std::string> il)
{
range_initialize(il.begin(), il.end());
}
StrVec::~StrVec()
{
free();
}
StrVec& StrVec::operator = (const StrVec &rhs)
{
auto data = alloc_n_copy(rhs.begin(), rhs.end());
free();
elements = data.first;
first_free = cap = data.second;
return *this;
}
void StrVec::push_back(const std::string &s)
{
chk_n_alloc();
alloc.construct(first_free++, s);
}
pair<string*, string*> StrVec::alloc_n_copy(const string *b, const string *e) {
auto data = alloc.allocate(e - b);
return { data, std::uninitialized_copy(b,e, data) };
}
void StrVec::reallocate()
{
auto newcapacity = size() ? 2 * size() : 1;
alloc_n_move(newcapacity);
}
void StrVec::alloc_n_move(size_t new_cap)
{
auto newdata = alloc.allocate(new_cap);
auto dest = newdata;
auto elem = elements;
for (size_t i = 0; i != size(); ++i)
alloc.construct(dest++, std::move(*elem++));
free();
elements = newdata;
first_free = dest;
cap = elements + new_cap;
}
void StrVec::free()
{
if (elements) {
for (auto p = first_free; p != elements;)
alloc.destroy(--p);
alloc.deallocate(elements, cap - elements);
}
}
void StrVec::reserve(size_t new_cap)
{
if (new_cap <= capacity()) return;
alloc_n_move(new_cap);
}
void StrVec::resize(size_t count)
{
resize(count, std::string());
}
void StrVec::resize(size_t count, const std::string &s)
{
if (count > size()) {
if (count > capacity()) reserve(count * 2);
for (size_t i = size(); i != count; ++i)
alloc.construct(first_free++, s);
}
else if (count < size()) {
while (first_free != elements + count)
alloc.destroy(--first_free);
}
}
bool operator==(const StrVec &lhs, const StrVec &rhs)
{
return (lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin()));
}
bool operator!=(const StrVec &lhs, const StrVec &rhs)
{
return !(lhs == rhs);
}
bool operator<(const StrVec &lhs, const StrVec &rhs)
{
return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
}
bool operator>(const StrVec &lhs, const StrVec &rhs)
{
return rhs < lhs;
}
bool operator<=(const StrVec &lhs, const StrVec &rhs)
{
return !(rhs < lhs);
}
bool operator>=(const StrVec &lhs, const StrVec &rhs)
{
return !(lhs < rhs);
}
StrVec& StrVec::operator=(std::initializer_list<std::string> il)
{
*this = StrVec(il);
return *this;
}
8. Quote类
8.1 Quote类头文件 —— 继承的使用
父类中的所有函数子类都可以通通调用,根据是否需要子类进行重新定义可以分为以下三类:
- non-virtual函数:不希望子类被重新定义
- virtual函数:希望子类重新定义(有默认的定义)
- pure virtual函数:希望子类一定要重新的定义(没有默认的定义)
#pragma once
#ifndef QUOTE
#define QUOTE
#include <iostream>
class quote
{
public:
quote() = default;
quote(std::string &book, double p) :
bookNo(book), price(p) { }
virtual double net_price(std::size_t sz)const
{
return sz * price;
}
protected:
double price = 0.0;
private:
std::string bookNo = "";
};
class disc_quote : public quote
{
public:
disc_quote() = default;
disc_quote(std::string &book, double p, double disc, std::size_t num) :
quote(book, p), discount(disc), limit_num(num) { }
double net_price(std::size_t sz)const = 0;
protected:
double discount = 0.0;
std::size_t limit_num = 0;
};
class bulk_quote : public disc_quote
{
public:
bulk_quote() = default;
bulk_quote(std::string &book, double p, double disc, std::size_t num) :
disc_quote(book, p, disc, num) { }
double net_price(std::size_t sz)const override
{
if (sz > limit_num)
return (sz - limit_num) * price * discount + limit_num * price;
else
return sz * price;
}
private:
};
#endif
9. 静态实现单例设计模式
class A
{
public:
static A& getInstance {return a; };
setup(){......}
private:
A();
A(const A& rhs);
...
};
A& A::getInstance()
{
static A a;
return a;
}
A::getInstance().setup();
10. 委托(pImpl)
委托关系(通过指针的复合,一个类A中有另一个类B的指针,A中要有big three),通过一个Handle类存有另一个实现类的指针,从而将其调用,这样的方法也会经常用到,实现类的变动不会影响Handle类。
10.1 pImpl头文件
class StringRep;
class String {
public:
String();
String(const char* s);
String(const String& s);
String &operator=(const String& s);
~String();
...
private:
StringRep* rep;
};
10.2 pImpl执行文件
#include "String.hpp"
namespace {
class StringRep {
friend class String;
StringRep(const char* s);
~StringRep();
int count;
char* rep;
};
}
String::String() {...}
...
10.3 委托+继承类模板
class Subject {
int m_value;
vector<Observer*> m_views;
public:
void attach(Observer* obs)
{
m_views.push_back(obs);
}
void set_val(int value)
{
m_value = value;
notify();
}
void notify()
{
for(int i = 0; i < m_views.size(); ++i)
m_views[i]->update(this, m_value);
}
}
class Observer
{
public:
virtual void update(Subject* sub, int value) = 0;
}
10.4 文件系统类
class Component
{
int value;
public:
Component(int val) { value = val; }
virtual void add(Component*) { }
}
class Primitive : public Component
{
public:
Primitive(int val) : Component(val) {}
}
class Composite : public Component
{
vector<Component*> c;
public:
Composite(int val) : Component(val) {}
void add(Component* elem) {
c.push(elem);
}
...
}
11. 分数类
class Fraction
{
public:
explicit Fraction(int num, int den = 1)
: m_numerator(num), m_denominator(den)
{ cout << m_numerator << ' ' << m_denominator << endl; }
operator double() const {
return (double)m_numerator / m_denominator;
}
Fraction operator+(const Fraction& f) {
cout << "operator+(): " << f.m_numerator << ' ' << f.m_denominator << endl;
return f;
}
private:
int m_numerator;
int m_denominator;
};
void test_conversion_functions()
{
cout << "test_conversion_functions()" << endl;
Fraction f(3,5);
double d = 4 + f;
cout << d << endl;
}
12. 智能指针类
12.1 智能指针类头文件
template<class T>
class shared_ptr
{
public:
T& operator*() const { return *px; }
T* operator->() const { return px; }
shared_ptr(T* p) : px(p) { }
private:
T* px;
long* pn;
}
struct Foo
{
...
void method(void);
...
}
int main()
{
shared_ptr<Foo> sp(new Foo);
Foo f(*sp);
sp->method();
}
12.2 迭代器类头文件
T& operator*() const { return (*node).data; }
T* operator->() const { return &(operator*()); }
13. 函数类
- 仿函数一般要继承一些奇怪的基类。
- 含有重载()的就是仿函数。
13.1 读取字符串仿函数类
class GetInput
{
public:
GetInput(std::istream &i = std::cin) : is(i) {}
std::string operator()() const
{
std::string str;
std::getline(is, str);
return is ? str : std::string();
}
private:
std::istream &is;
};
void test()
{
GetInput getInput;
std::vector<std::string> vec;
for (std::string tmp; !(tmp = getInput()).empty();) vec.push_back(tmp);
for (const auto &str : vec) std::cout << str << " ";
std::cout << std::endl;
}
13.2 判断两数是否相等仿函数类
class IsEqual
{
int value;
public:
IsEqual(int v) : value(v) {}
bool operator()(int elem)
{
return elem == value;
}
};
void test()
{
std::vector<int> vec = { 3, 2, 1, 4, 3, 7, 8, 6 };
std::replace_if(vec.begin(), vec.end(), IsEqual(3), 5);
for (int i : vec) std::cout << i << " ";
std::cout << std::endl;
}
14. 模板类
14.1 复数类
template<typename T>
class complex
{
public:
complex (T r = 0, T i = 0) :
re(r), im(i) {}
complex& operator += (const complex&);
T real() const { return re; }
T imag() const { return im; }
private:
T re, im;
friend complex& __doapl (complex*, const complex&);
}
void test()
{
complex<double> c1(2.5, 1.5);
complex<int> c2(2, 6);
}
15. 函数模板
- 函数模板在使用的时候不必指明模板类型,编译器自动进行实参推导。
template<class T>
inline
const T& min(const T& a, const T& b)
{
return b < a ? b : a;
}
class stone
{
public:
stone(int w, int h, int we) :
_w(w), _h(h), _weight(we) {}
bool operator< (const stone& rhs) const
{
return _weight < rhs._weight;
}
private:
int _w, _h, _weight;
}
void test()
{
stone r1(2, 3), r2(3, 3), r3;
r3 = min(r1, r2);
}
16. 成员模板
template <class T1, class T2>
class pair
{
public:
pair() : first(T1()), second(T2()) {}
pair(const T1& a, const T2& b) :
first(a), second(b) {}
template<class U1, class U2>
pair(const pair<U1, U2>& p) :
first(p.first), second(p.second) {}
}
class Base1 {};
class Derived1 : pubic Base1 {};
class Base2 {};
class Derived2 : public Base2 {};
17. 模板特化
17.1 模板特化
template <class key>
struct hash {};
template<>
struct hash<char> {
size_t operator()(char x) const { return x; }
};
template<>
struct hash<int> {
size_t operator()(int x) const { return x; }
};
template<>
struct hash<char> {
size_t operator()(long x) const { return x; }
};
void test()
{
std::cout << hash<long>()(1000);
}
17.2 模板偏特化
17.2.1 个数的偏
template<typename T, typename Alloc=...>
class vector
{
...
};
template<typename Alloc=...>
class vector<bool, Alloc>
{
...
};
17.2.2 范围的偏
template<typename T>
class C
{
...
};
template<typename T>
class C<T*>
{
...
}
void test()
{
C<string> obj1;
C<string*> obj2;
}
18. 模板模板参数
18.1 模板模板参数实例
template <typename T,
template <typename T>
class SmartPtr
>
class XCls
{
private:
SmartPtr<T> sp;
public:
XCls() : sp(new T) {}
}
void test()
{
XCls<string, shared_ptr> p1;
XCls<long, auto_ptr> p2;
}
18.2 非模板模板参数
template <class T, class Sequence = deque<T>>
class stack
{
...
protected"
Sequence x;
}
void test()
{
stack<int> s1;
stack<int, list<int>> s2;
}
19. 数量不定的模板参数
void print() { }
template <typename T, typename... Types>
void print(const T& firstArg, const Types&... args)
{
cout << firstArg << endl;
print(args...);
}
20. 对象模型
21. 重载new、delete
21.1 全局new、delete重载
void* myAlloc(size_t size)
{
return malloc(size);
}
void myFree(void* ptr)
{
return free(ptr);
}
inline
void* operator new(size_t size)
{
cout << "jjhou global new() \n";
return myAlloc(size);
}
inline
void* operator new[](size_t size)
{
cout << "jjhou global new[]() \n";
return myAlloc(size);
}
inline
void operator delete(void* ptr)
{
cout << "jjhou global delete() \n";
myFree(ptr);
}
inline
void operator delete[](void* ptr)
{
cout << "jjhou global delete[]() \n";
myFree(ptr);
}
21.2 类中new、delete重载
class Foo
{
public:
void* operator new(size_t);
void operator delete(void*, size_t);
}
void test()
{
Foo* p = new Foo;
...
delete p;
}
try
{
void *mem = operator new(sizeof(Foo));
p = static_cast<Foo*>(mem);
p->Foo::Foo();
}
p->~Foo();
operator delete(p);
21.3 类中new[]、delete[]重载
class Foo
{
public:
void* operator new[](size_t);
void operator delete[](void*, size_t);
};
void test()
{
Foo* p = new Foo [N];
...
delete [] p;
}
try
{
void *mem = operator new(sizeof(Foo) * N + 4);
p = static_cast<Foo*>(mem);
p->Foo::Foo();
}
p->~Foo();
operator delete(p);
21.4 类中new、delete重载完整代码
class Foo
{
public:
int _id;
long _data;
string _str;
public:
Foo() : _id(0) { cout << "default ctor.this=" << this << "id=" << _id << endl; }
Foo(int i) : _id(i) { cout << "default ctor.this=" << this << "id=" << _id << endl; }
~Foo() { cout << "dtor.this=" << this << "id=" << _id << endl;}
void* operator new(size_t size) {
Foo* p = (Foo*)malloc(size);
cout << ...
return p;
}
void* operator new[](size_t size) {
Foo* p = (Foo*)malloc(size);
cout << ...
return p;
}
void operator delete(void* pdead, size_t size) {
cout << ...
free(pdead);
}
void operator delete[](void* pdead, size_t size) {
cout << ...
free(pdead);
}
};
21.4 类中new()、delete()重载
class Foo
{
public:
Foo() { cout << "Foo::Foo()" << endl; }
Foo(int) { cout << "Foo::Foo(int)" << endl; throw Bad(); }
~Foo() { cout << "dtor.this=" << this << "id=" << _id << endl;}
void* operator new(size_t size) {
return malloc(size);
}
void* operator new(size_t size, void* start) {
return start;
}
void* operator new(size_t size, long extra) {
return malloc(size + extra);
}
void* operator new(size_t size, long extra, char init) {
return malloc(size + extra);
}
void operator delete(void*, size_t) {
cout << "operator delete(void*, size_t)" << endl;
}
void operator delete(void*, void*) {
cout << "operator delete(void*, void*)" << endl;
}
void operator delete(void*, long) {
cout << "operator delete(void*, long)" << endl;
}
void operator delete(void*, long, char) {
cout << "operator delete(void*, long, char)" << endl;
}
};
|