chapter 7类

chapter 7类,第1张

文章目录
  • 前言
  • chapter 7 class
    • constructor
    • 隐式类类型转换
  • 类的静态成员


前言

  介绍了类的基本内容。


chapter 7 class
#include 
#include 
using std::istream;
using std::ostream;
using std::string;

class Sales_data{
//友元声名,并非函数声名,可以在友元声名的同时定义该函数,也必须声明过
friend Sales_data add(const Sales_data&, const Sales_data&);
friend istream & read(istream&, Sales_data&);
friend ostream & print(ostream&, const Sales_data&);
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&is);

    // 成员函数,声名必须在内部,定义不要求
    // 定义在类内部,隐式的inline函数
    // 编译器分两步处理类:1.编译成员声名 2.成员函数体
    string isbn() const {return bookNo;} 
    Sales_data& combine(const Sales_data&) ; // 常量成员函数
private:
    double avg_price() const;
    // 数据成员
    string bookNo;
    unsigned int units_sold = 0;
    double revenue = 0;
};
// 非成员接口函数,声名应该与类在同一个头文件内
Sales_data add(const Sales_data&, const Sales_data&);
ostream &print(ostream&, const Sales_data&);
istream &read(istream&, Sales_data&);

// 定义在类外部的成员函数
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;
}
// IO类不能被拷贝
ostream & print(ostream&os, const Sales_data&item){
    os << item.isbn() << " " << item.units_sold << " "
    << item.revenue << " " << item.avg_price();
    return os;
}
Sales_data add(const Sales_data&item1, const Sales_data&item2){
    Sales_data sum = item1; //拷贝类的对象
    return sum.combine(item2);
}

// 构造函数内部声名,外部定义
// 构造函数没有返回类型
// 因为函数名和类名相同,所以它是构造函数
Sales_data::Sales_data(istream &is){
    read(is, *this); //read,从is中读取一条交易信息然后
                     //存入this对象中
}
int main(){
    Sales_data total;
    if (read(cin, total)){
        Sales_data trans;
        while (read(cin, trans)){
            if (total.isbn() == trans.isbn()){
                total.combine(trans);
            }else{
                print(cout, total) << endl;
                total = trans;
            }
        }
        print(cout, total) << endl;
    }else{
        cout << "No data?!" << endl;
    } 
    // Sales_data item1 = {"jskf", 4, 89};
    // print(cout, item1) << endl;
}

构造函数
相当于 __init__,
构造函数初始值列表

//构造函数初始值列表
Sales_data(const std::string&s, unsigned n, double p):
	bookNo(s), units_sold(n), revenue(p*n) {}
// : bookNo(s), units_sold(n), revenue(p*n)  称为 构造函数初始值列表

  this的类型是指向类类型非常量版本的常量指针,它指向的对象是一个非常量。在形参列表后添加const代表this指向的是一个常量。

  类内初始值必须以符号 = 或者花括号表示。

类的声名和定义
类的对象被创建时必须完全定义类,类声名后即可有指向类的指针或引用

class Y;
class X{
public:
    Y *haha;
};

class Y{
public:
    X haha;
};

friend可以时函数、类、类的成员函数
友元不具传递性

友元仅仅影响函数权限

7.3.4节练习

class WindowMgr{
private:
    std::vector<Screen> screens{Screen(24, 80, ' ')};
public:
    void clear(Screen &);
};

class Screen{
friend void WindowMgr::clear(Screen &);
public:
    using pos = std::string::size_type;
    // typedef std::string::size_type pos;
    Screen(/* args */)=default;
    // ~Screen();
    Screen(pos a, pos b, char c):
        contents(a*b, c), height(a), width(b){}
    // Screen &display(ostream&) const;
    //Screen &display(ostream &os){do_display(os); return *this;}
    //const Screen &display(ostream &os) const{do_display(os); return *this;}
private:
    string contents;
    pos cursor = 0, height = 0, width = 0;
    /*void do_display(ostream &os) const{
        for (int i=0;i
};

Screen &clear(Screen &scrn){
    string temp(scrn.width*scrn.height, ' ');
    scrn.contents = temp; //为什么scrn.contents = " "就不行??
    return scrn;
}
constructor

构造函数:

//初始化
Sales_data::Sales_data(const string &s, unsigned cnt, double price):
  	bookNo(s), units_sold(cnt), revenue(cnt * price){}
//赋值
Sales_data::Sales_data(const string &s, unsigned cnt, double price){
	bookNo = s; units_sold = cnt; revenue = cnt * price;
}

初始化 *** 作和赋值 *** 作不同

  • 如果成员是const或者引用,必须初始化

类的成员初始化顺序与构造函数初始值列表顺序无关,按照在类中的定义顺序进行
最好令构造函数初始值的顺序与成员声名的顺序保持一致。而且如果可能的话,尽量避免使用某些成员初始化其他成员。
默认实参和构造函数

委托构造函数

class Sales_data{
public:
    Sales_data(std::string s, unsigned cnt, double price): 
        bookNo(s), units_sold(cnt), revenue(cnt*preice){}
    Sales_data():Ssles_data("", 0, 0) {}
    Sales_data(std::string s):Sales_data(s, 0, 0) {}
    Sales_data(std::istream &is):Sales_data() {read(is, *this);}
};
隐式类类型转换
//只能一步
string s = "abc";
item.combine(s);                 // ✔
item.combine(Salse_data("abc")); // ✔
item.combine(string("abc")) ;    // ✔
item.combine("abc");             // ✔

//以制自动隐式类类型转换
// explicit关键字只允许出现在类内的构造函数声名处
explicit Sales_data(const std::string &s):bookNo(s){}
item.combine(s);                // ❌

Sales_data item1(null_book);    // ✔直接初始化
Sales_data item2 = null_book;   // ❌不能将explicit构造函数用于拷贝形式的初始化过程

//显式强制转换

聚合类
缺点较为明显,不建议使用

struct Data{
    int ival;
    string s;
};
Data val1 = {0, "Anna"}; // 顺序必须一致

字面值常量类

类的静态成员

声名静态成员
需要在类的外部定义
(有点像python中的类属性)

class Account{
public:
    void calculate() {amount += amount * interestRate;}
    // static关键字只能出现在类内
    static double rate() {return interestRate;}
    static void rate(double);
private:
	std::string owner;
	double amount;
	static double interestRate;
	static double initRate();
};
//使用类的静态成员
double r;
r = Account::rate();
Account ac1, *ac2 = &ac1;
r = ac1.rate();
r = ac2 -> rate ();     //emm 果然和python一样

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/713527.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-24
下一篇 2022-04-24

发表评论

登录后才能评论

评论列表(0条)

保存