C++学习总结

一、static类成员

1、static类成员是与类相关联的,类定义时就存在,它独立于类的任何对象而存在。因此可以通过类、类的对象、类的对象指针、类的对象的引用来访问,同时也说明了他没有this指针。

2、static相当于一个全局变量。但是它可以是私有的(可以实施封装)。

3、static成员不是通过类构造函数进行初始化,而是应该在定义时进行初始化。

4、static 成员函数不能被声明为 const(注意,是成员函数,不是成员变量,成员变量可以为static const类型)。毕竟,将成员函数声明为const 就是承诺不会修改该函数所属的对象。

5、static 成员函数也不能被声明为虚函数。

二、纯虚函数

1、在函数形参表后面写上 = 0 以指定纯虚函数:

     class Disc_item : public Item_base {
     public:
         double net_price(std::size_t) const = 0;
     };


2、定义了纯虚函数后,包含该纯虚函数的类将无法实例化,只能被其他类继承(抽象基类)。

3、派生类如果继承了抽象基类,而在该派生类中没有对此纯虚函数进行定义   则该派生类扔为抽象类 不能用它实体定义对象 

三、容器与继承

1、句柄的引入

如果定义 multiset 保存基类类型的对象:

     multiset<Item_base> basket;
     Item_base base;
     Bulk_item bulk;
     basket.insert(base);  // ok: add copy of base to basket
     basket.insert(bulk);  // ok: but bulk sliced down to its base part

一旦对象放入了 multiset,它就不再是派生类对象了。容器中加入派生类型的对象时,只将对象的基类部分保存在容器中。记住,将派生类对象复制到基类对象时,派生类对象将被切掉

2、定义句柄类

句柄类将有两个数据成员,都是指针:一个指针将指向 基类 对象,而另一个将指向使用计数。句柄类 指针可以指向 基类对象也可以指向基类的 派生类型的对象。通过指向使用计数,多个 句柄类 对象可以共享同一计数器。(类似于智能指针)

3、句柄类与容器

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

class Item_base
{  
public: 
    Item_base(const string &book = "", double sales_price = 0.0):isbn(book), price(sales_price){};//构造函数
	Item_base(const Item_base &other)
	{
		isbn = other.isbn;
		price = other.price;
	}
	virtual Item_base* clone() const//为了使句柄类能够复制未知类型而定义
    { 
		return new Item_base(*this); 
	};

	string book() const
	{
		return isbn;
	};

	virtual double net_price(size_t n) const//打折后的价格
	{
		return n*price;
	}; 

	virtual ~Item_base();
private:  
    string isbn;
protected:
    double price;  
};  

class Disc_item : public Item_base  //Disc_item为虚基类
{
public:
	Disc_item(const string & book = "", double sales_price = 0.0, size_t qty = 0, double disc_rate = 0.0):
		Item_base(book, sales_price), quantity(qty), discount(disc_rate){};
	~Disc_item();
protected:
	size_t quantity; // purchase size for discount to apply
    double discount;      // fractional discount to apply
	//纯虚函数,该类无法实例化,只能被其他类继承
	double net_price(size_t) const = 0;//discount
};

class Bulk_item : public Disc_item
{
//1、派生类的构造函数:
//派生类构造函数只能初始化自己的直接基类,在 Bulk_item 类的构造函数初始化列表中指定 Item_base 是一个错误。
public:
	Bulk_item(const string& book = "", double sales_price = 0.0, size_t qty = 0, double disc_rate = 0.0):
		Disc_item(book, sales_price, qty, disc_rate) { };
	~Bulk_item();
	
	Bulk_item* clone() const//为了使句柄类能够复制未知类型而定义
	{ 
		return new Bulk_item(*this); 
	}

//2、关于派生类的复制构造函数:
//只包含类类型或内置类型数据成员、不含指针的类一般可以使用合成操作,复制、赋值或撤销这样的成员不需要特殊控制。
//具有指针成员的类一般需要定义自己的复制控制来管理这些成员
protected:
	double net_price(size_t n) const
	{
		return n*price;
	};
private:
};

class Sales_item  //句柄类 use counted handle class for the Item_base hierarchy
{
public:
	// default constructor: unbound handle
	Sales_item(): p(0), use(new size_t(1)) { };
	
	// 句柄的复制构造函数,attaches a handle to a copy of the Item_base object
	//为了句柄类,需要从基类开始,在继承层次的每个类型中增加 clone,基类必须将该函数定义为虚函数
	Sales_item(const Item_base &item):p(item.clone()), use(new size_t(1)) { };

	// copy control members to manage the use count and pointers
	Sales_item(const Sales_item &i):p(i.p), use(i.use)
	{ 
		++*use; 
	}

	~Sales_item() 
	{ 
		decr_use(); 
	}
	
	Sales_item& operator=(const Sales_item &rhs) // use-counted assignment operator; use is a pointer to a shared use count
	{
		++*rhs.use;
		decr_use();
		p = rhs.p;
		use = rhs.use;
		return *this;
	};

	// member access operators
	const Item_base* operator->() const 
	{ 
		if (p) 
			return p;
		else 
			throw std::logic_error("unbound Sales_item");
	}
	const Item_base& operator*() const 
	{ 
		if (p) 
			return *p;
		else 
			throw std::logic_error("unbound Sales_item"); 
	}
	// 比较函数,compare defines item ordering for the multiset in Basket
	inline bool compare(const Sales_item &lhs, const Sales_item &rhs)
	{
		return lhs->book() < rhs->book();
	}

private:
	Item_base *p;        // pointer to shared item
	size_t *use;    // pointer to shared use count
	// called by both destructor and assignment operator to free pointers
	void decr_use()
	{ 
		if (--*use == 0) 
		{ 
			delete p; 
			delete use; 
		} 
	}
};

class Basket//跟踪销售并计算购买价格 
{
	typedef bool (*Comp)(const Sales_item&, const Sales_item&);//这个语句将 Comp 定义为函数类型指针的同义词,该函数类型与我们希望用来比较 Sales_item 对象的比较函数相匹配。
public:
	// make it easier to type the type of our set
	typedef multiset<Sales_item, Comp> set_type;
	// typedefs modeled after corresponding container types
	typedef set_type::size_type size_type;
	typedef set_type::const_iterator const_iter;
	Basket(): items(compare) { } // initialze the comparator
	void add_item(const Sales_item &item)
	{ 
		items.insert(item); 
	}
	size_type size(const Sales_item &i) const
	{ 
		return items.count(i); 
	}
	double total() const; // 返回购物篮中所有物品的价格
	{
		double sum = 0.0; // holds the running total
		
						  /* find each set of items with the same isbn and calculate
						  * the net price for that quantity of items
						  * iter refers to first copy of each book in the set
						  * upper_bound refers to next element with a different isbn
		*/
		for (const_iter iter = items.begin(); iter != items.end(); iter = items.upper_bound(*iter))
		{
			// we know there's at least one element with this key in the Basket
			// virtual call to net_price applies appropriate discounts, if any
			sum += (*iter)->net_price(items.count(*iter));
		}
		return sum;
	}
private:
	multiset<Sales_item, Comp> items;
};

int main()
{
	Item_base base("0-201-82470-1", 20);
//  Disc_item无法实例化
//	Disc_item Disc("0-201-82470-1", 20, 19, 19);
	
	Bulk_item bulk("0-201-82470-1", 20, 19, 19);
	multiset <Sales_item> basket;//购物车
	basket.insert(base);
	basket.insert(bulk);
	cout<<base.book();
	return 0;
}


posted @ 2013-12-13 17:58  action爱生活  阅读(256)  评论(0编辑  收藏  举报