• 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;
    }
    


  • 相关阅读:
    vue教程2-06 过滤器
    vue教程2-05 v-for循环 重复数据无法添加问题 加track-by='索引'
    vue教程2-04 vue实例简单方法
    Linux文件I/O
    Linux内存管理
    进程中内存地址空间的划分
    Ubuntu12.04 15.04禁止移动介质自动播放
    条件编译,头文件,静态库,共享库与多文件编程
    C语言的函数
    C语言流程控制
  • 原文地址:https://www.cnblogs.com/actionke/p/4192635.html
Copyright © 2020-2023  润新知