chapter-7

作者: 峡迩 | 来源:发表于2017-07-13 22:30 被阅读0次
// chapter-7.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include<iostream>
#include<string>
#include<vector>

using namespace std;

class Sales_data                                    //第一个访问说明符之前的成员属性由class和struct决定,class默认private,struct默认public
{
    // 定义友元,外部函数可以访问非共有成员(protected,private)
    friend Sales_data add(const Sales_data &lhs, const Sales_data &rhs);
    friend ostream &print(ostream &os, Sales_data &item);   //声明为其友元函数,可以访问非共有成员。(友元声明并不是一个完整意义的函数声明!)
    friend istream &read(istream &is, Sales_data &item);

public:                                             //都可访问

    //构造函数
    Sales_data() = default;                         //只有当类没有声明任何构造函数时,才会自动生成默认构造函数
    Sales_data(const string &s) :bookNo(s) {};
    Sales_data(const string &s, unsigned n, double p) :bookNo(s), units_sold(n), revenue(p*n) {};
    Sales_data(istream &);

    string isbn() const { return bookNo; };         //默认使用this,等价于this->bookNo;使用const改变this指针为指向常量(底层const)的常量指针(this默认为常量指针(顶层const)),提高函数的灵活性!指向常量的常量指针函数,才可以使常量对象调用普通成员函数!此函数有前提条件,在函数体内不会改变this所指向的对象!
    Sales_data &combine(const Sales_data&);
    double avg_price() const;
//protected:                                            //外部不可访问,继承可以访问!

  private:                                          //外部和继承不可访问,使用封装有2个重要的好处:1、确保用户不会无意间破坏封装对象;2、被封住的类具体实现细节可以随时修改,而无须调整用户级别的代码。
    string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
};

//Sales_data非成员接口函数
Sales_data add(const Sales_data &lhs, const Sales_data &rhs);
ostream &print(ostream &os, Sales_data &item);          //函数声明时候,形参等必须相同!
istream &read(istream &is, Sales_data &item);

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

Sales_data& Sales_data::combine(const Sales_data &rhs)
{
    units_sold += rhs.units_sold;
    revenue += rhs.revenue;
    return *this;                                       //返回调用该函数的对象。
}

istream &read(istream &is, Sales_data &item)
{
    double price = 0;
    is >> item.bookNo >> item.units_sold >> price;
    item.revenue = price*item.units_sold;
    return is;
}

//Sales_data(istream &)构造函数
Sales_data::Sales_data(istream &is)
{
    read(is, *this);
}

ostream &print(ostream &os, Sales_data &item)
{
    os << item.isbn() << " " << item.units_sold << " " << item.revenue << " " << item.avg_price();
    return os;
}

Sales_data add(const Sales_data &lhs, const Sales_data &rhs)
{
    Sales_data item = lhs;
    item.combine(rhs);
    return item;
}

class Screen
{
    friend class window_mgr;                //定义window_mgr为screen的友元类!,则window_mgr中的函数可以访问screen中的非公有成员!
                                            //友元关系不存在传递关系,每个类定义自己的友元!
public:
    using pos = string::size_type;
    Screen() = default;
    Screen(pos ht, pos wd, char c) :height(ht), width(wd), contents(ht*wd, c) {}
    char get()const                                 //隐式内联
    {
        return contents[cursor];    
    }
    inline char get(pos ht, pos wd) const;          //类内成员函数是自动的inline,也可以用inline直接声明内联函数。
    Screen &move(pos r, pos c);

    Screen &set(char c)
    {
        contents[cursor] = c;
        return *this;
    }
    Screen &set(pos r, pos col, char ch)            //返回*this对象的引用(即对象本身)
    {
        contents[r*width + col] = ch;
        return *this;
    }

    Screen &displsy(ostream &os)                //只能传入非常量版本,返回类型为非常量的引用!
    {
        do_display(os);
        return *this;
    }
    const Screen &displsy(ostream &os) const            //如果为const成员函数,则返回类型将是常量!????有什么问题没???
    {
        do_display(os);
        return *this;
    }

    void some_member()const;

private:
    pos cursor = 0;
    pos height = 0, width = 0;
    string contents;

    mutable pos access_ctr = 0;

    void do_display(ostream &os) const { os << contents; }
};

void Screen::some_member() const
{
    ++access_ctr;               //变量声明为可变数据成员,即使在const成员函数,还是可以改变access_ctr的值!
}

inline Screen &Screen::move(pos r, pos c)
{
    pos row = r*width;
    cursor = row + c;
    return *this;
}
char Screen::get(pos r, pos c) const
{
    pos row = r*width;
    return contents[row + c];
}

class window_mgr
{
public:
    void clear(vector<Screen>::size_type i)
    {
        Screen &s = screens[i];
        s.contents = string(s.height*s.width, ' ');
    }
private:
    vector<Screen> screens{ Screen(24,80,' ') };            //类作为类内数据成员时,初始化方法!
};

class ConstRef
{
public:
    ConstRef() = default;
    ConstRef(int i):ii(i),ci(i),ri(i){}             //引用和const必须初始化!建议养成构造函数初始化的习惯!
private:
    int ii;
    const int ci;
    int &ri;
};

class Data
{
public:
    //非委托构造函数
    Data(string s,string::size_type i,double p):item(s),cnt(i),price(p){}
    //委托构造函数
    Data():Data(" ",0,0){}
    Data(string s):Data(s,0,0){}
    Data(istream &is) :Data() { is >> item; }
private:
    string item;
    string::size_type cnt=0;
    double price=0.0;
};
//聚合类,所有成员都是public,没有定义任何构造函数,没有类内初始值,没有基类也没有virtual函数!使用花括号进行成员初始化
struct Data
{
        int ival;
        string s;
}
Data val9={0,"Anna"};
int main()
{
    Sales_data s1(cin);             //使用构造函数Sales_data(istream &)创建对象


    Screen myscreen(5, 3,' ');
    const Screen myscreen_const(5,3,' ');       //常量screen对象。
    myscreen.set('#').displsy(cout);
    cout << endl;
    myscreen_const.displsy(cout);               //调用常量版本函数

    //Data obj1();
    //Data obj2;                                直接使用这种声明,定义一个默认初始化的对象!

    cin.ignore();
    return 0;
}

//类基本思想是数据抽象和封装。数据抽象依赖于接口和实现,接口包含用户所能执行的操作,实现包含类的数据成员、函数;封装实现了接口和实现的分离,用户只可以访问接口,而无法访问实现!
//类的定义分两步,1、编译成员声明;2、直到类全部可见后才编译函数体。
//类的构造函数,如果成员对象为const或者引用,则必须进行初始化!
//类的静态成员,所有类对象共用,可以通过对象、引用或者指针访问它~在类内声明,在类外定义!
//优秀的设计者应该关注那些有可能使用该类的程序员的需求,作为一个设计良好的类,既要有直观且易于使用的接口,也必须具备高效的实现过程!

const在函数形参,实参,返回类型的区别?
const int &i,常量引用形参!,在类内const成员函数为常量返回类型!(常量版本的函数),程序有必要同时定义一个非常量版本的函数!

相关文章

  • chapter-7

    const在函数形参,实参,返回类型的区别?const int &i,常量引用形参!,在类内const成员函数为常...

  • Chapter-7[内存管理-段式内存管理]

    一、分页系统的缺点 分页系统存在的一个无法容忍,同时也是分页系统无法解决的一个缺点就是:一个进程只能占有一个虚拟地...

网友评论

      本文标题:chapter-7

      本文链接:https://www.haomeiwen.com/subject/gziehxtx.html