C++ Primer (第五版)-第七章 类

一、概述

在这里插入图片描述
在这里插入图片描述

二、内容

7.1 定义抽象数据类型

#ifndef SALES_DATA_H
#define SALES_DATA_H

#include "Version_test.h"

#include <string>
#include <iostream>

class Sales_data {
friend Sales_data add(const Sales_data&, const Sales_data&);
friend std::ostream &print(std::ostream&, const Sales_data&);
friend std::istream &read(std::istream&, Sales_data&);
public:
	// constructors
// using the synthesized version is safe only
// if we can also use in-class initializers
#if defined(IN_CLASS_INITS) && defined(DEFAULT_FCNS)
	Sales_data() = default;
#else
	Sales_data(): units_sold(0), revenue(0.0) { }
#endif
#ifdef IN_CLASS_INITS
	Sales_data(const std::string &s): bookNo(s) { }
#else
	Sales_data(const std::string &s): 
	           bookNo(s), units_sold(0), revenue(0.0) { }
#endif
	Sales_data(const std::string &s, unsigned n, double p):
	           bookNo(s), units_sold(n), revenue(p*n) { }
	Sales_data(std::istream &);

	// operations on Sales_data objects
	std::string isbn() const { return bookNo; }
	Sales_data& combine(const Sales_data&);
	double avg_price() const;
private:
	std::string bookNo;
#ifdef IN_CLASS_INITS   // using the synthesized version is safe only
	unsigned units_sold = 0;
	double revenue = 0.0;
#else
	unsigned units_sold;
	double revenue;
#endif
};


// nonmember Sales_data interface functions
Sales_data add(const Sales_data&, const Sales_data&);
std::ostream &print(std::ostream&, const Sales_data&);
std::istream &read(std::istream&, Sales_data&);

// used in future chapters
inline 
bool compareIsbn(const Sales_data &lhs, const Sales_data &rhs)
{
	return lhs.isbn() < rhs.isbn();
}
#endif
#include <iostream>
using std::istream; using std::ostream;

#include "Sales_data.h"
Sales_data::Sales_data(std::istream &is) 
{
	// read will read a transaction from is into this object
	read(is, *this);
}

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

// add the value of the given Sales_data into this object
Sales_data& 
Sales_data::combine(const Sales_data &rhs)
{
	units_sold += rhs.units_sold; // add the members of rhs into 
	revenue += rhs.revenue;       // the members of ``this'' object
	return *this; // return the object on which the function was called
}

Sales_data 
add(const Sales_data &lhs, const Sales_data &rhs)
{
	Sales_data sum = lhs;  // copy data members from lhs into sum
	sum.combine(rhs);      // add data members from rhs into sum
	return sum;
}

// transactions contain ISBN, number of copies sold, and sales price
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;
}

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

在这里插入图片描述
在这里插入图片描述

c++this概念

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

定义类的相关非成员函数

在这里插入图片描述

构造函数

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

拷贝、赋值、析构

在这里插入图片描述

7.2、访问控制和封装

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

友元

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7.3、类的其他特性

#include "Version_test.h"

#include <string>
#include <iostream>

class Screen {
public:
    typedef std::string::size_type pos;
#if defined(IN_CLASS_INITS) && defined(DEFAULT_FCNS)
	Screen() = default;  // needed because Screen has another constructor
#else
	Screen(): cursor(0), height(0), width(0) { }
#endif
	// cursor initialized to 0 by its in-class initializer
    Screen(pos ht, pos wd, char c): height(ht), width(wd), 
	                                contents(ht * wd, c) { }
	friend class Window_mgr;
    Screen(pos ht = 0, pos wd = 0): 
       cursor(0), height(ht), width(wd), contents(ht * wd, ' ') { }
    char get() const              // get the character at the cursor
	    { return contents[cursor]; }       // implicitly inline
    inline char get(pos ht, pos wd) const; // explicitly inline
	Screen &clear(char = bkground);
private:
	static const char bkground = ' ';
public:
    Screen &move(pos r, pos c);      // can be made inline later
    Screen &set(char);
    Screen &set(pos, pos, char);
	// other members as before
    // display overloaded on whether the object is const or not
    Screen &display(std::ostream &os) 
                  { do_display(os); return *this; }
    const Screen &display(std::ostream &os) const
                  { do_display(os); return *this; }
private:
     // function to do the work of displaying a Screen
     void do_display(std::ostream &os) const {os << contents;}
	// other members as before
private:
#ifdef IN_CLASS_INITS
    pos cursor = 0;
    pos height = 0, width = 0;
#else
    pos cursor;
    pos height, width;
#endif
    std::string contents;
};

Screen &Screen::clear(char c) 
{
	contents = std::string(height*width, c);
	return *this;
}

inline                   // we can specify inline on the definition
Screen &Screen::move(pos r, pos c)
{
    pos row = r * width; // compute the row location
    cursor = row + c;    // move cursor to the column within that row
    return *this;        // return this object as an lvalue
}

char Screen::get(pos r, pos c) const // declared as inline in the class
{
    pos row = r * width;      // compute row location
    return contents[row + c]; // return character at the given column
}

inline Screen &Screen::set(char c) 
{ 
    contents[cursor] = c; // set the new value at the current cursor location
    return *this;         // return this object as an lvalue
}
inline Screen &Screen::set(pos r, pos col, char ch)
{
	contents[r*width + col] = ch;  // set specified location to given value
	return *this;                  // return this object as an lvalue
}
#include <iostream>
using std::cout; using std::endl;

#include <string>
using std::string;

#include "Screen.h"

int main()
{
	Screen myScreen(5,3);
	// move the cursor to a given position, and set that character 
	myScreen.move(4,0).set('#');

	Screen nextScreen(5, 5, 'X');
	nextScreen.move(4,0).set('#').display(cout);
	cout << "\n";
	nextScreen.display(cout);
	cout << endl;

	const Screen blank(5, 3);
	myScreen.set('#').display(cout);  // calls nonconst version
	cout << endl;
	blank.display(cout);              // calls const version
	cout << endl;

	myScreen.clear('Z').display(cout); cout << endl;
	myScreen.move(4,0);
	myScreen.set('#');
	myScreen.display(cout); cout << endl;
	myScreen.clear('Z').display(cout); cout << endl;

	// if move returns Screen not Screen&
	Screen temp = myScreen.move(4,0); // the return value would be copied
	temp.set('#'); // the contents inside myScreen would be unchanged
	myScreen.display(cout);
	cout << endl;
}

内联函数

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

返回*this的成员函数

在这里插入图片描述

const成员函数返回*this

在这里插入图片描述

基于const重载

在这里插入图片描述
在这里插入图片描述

类类型

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

友元再探

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#ifndef WINDOW_MGR
#define WINDOW_MGR

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

class BitMap;
// overloaded storeOn functions
extern std::ostream& storeOn(std::ostream &, Screen &);
extern BitMap& storeOn(BitMap &, Screen &);

class Window_mgr {
public:
	// location ID for each screen on the window
	using ScreenIndex = std::vector<Screen>::size_type;
	// add a Screen to the window and returns its index

	ScreenIndex addScreen(const Screen&);
	
	// reset the Screen at the given position to all blanks
	void clear(ScreenIndex);

	// change dimensions of a given Screen
	void resize(Screen::pos r, Screen::pos c, ScreenIndex i);
private:
	// Screens this Window_mgr is tracking
	// by default, a Window_mgr has one standard sized blank Screen 
	std::vector<Screen> screens{Screen(24, 80, ' ')};
};

// return type is seen before we're in the scope of Window_mgr
inline
Window_mgr::ScreenIndex
Window_mgr::addScreen(const Screen &s)
{
	screens.push_back(s);
	return screens.size() - 1;
}

inline
void Window_mgr::clear(ScreenIndex i)
{
	// s is a reference to the Screen we want to clear
	Screen &s = screens[i];
	// reset the contents of that Screen to all blanks
	s.contents = std::string(s.height * s.width, ' ');
}

inline
void
Window_mgr::resize(Screen::pos r, Screen::pos c, ScreenIndex i)
{
    screens[i].height = r;  // Window_mgr is a friend of Screen
    screens[i].width = c;   // so it is ok to use Screen's private members
	// resize and clear the contents member
	screens[i].contents = std::string(r * c, ' '); 
}

#endif

在这里插入图片描述

7.4、类的作用域

在这里插入图片描述
在这里插入图片描述

名字查找和类作用域,

在这里插入图片描述
在这里插入图片描述

#include "Version_test.h"

#ifndef ACCOUNT_H
#define ACCOUNT_H

#include <string>

class Account {
public:
#if defined(DEFAULT_FCNS) && defined(IN_CLASS_INITS)
	Account() = default;
#else
	Account(): amount(0.0) { }
#endif
	Account(const std::string &s, double amt):
		owner(s), amount(amt) { }

    void calculate() { amount += amount * interestRate; }
    double balance() { return amount; }
public:
    static double rate() { return interestRate; }
    static void rate(double);   
private:
    std::string owner; 
#ifdef IN_CLASS_INITS
    double amount = 0.0; 
#else
	double amount;
#endif
    static double interestRate; 
    static double initRate() { return .0225; }
    static const std::string accountType;
#ifdef CONSTEXPR_VARS
    static constexpr int period = 30;// period is a constant expression
#else
	static const int period = 30;// period is a constant expression
#endif
    double daily_tbl[period];
};
#endif
#include <string>
using std::string;

#include "Account.h"

// define static data and function members
const string Account::accountType("Savings Account");
double Account::interestRate = initRate();

void Account::rate(double newRate) 
{
    interestRate = newRate; 
}
#include <iostream>
using std::cout; using std::endl;

#include <string>
using std::string;

#include "Account.h"

int main()
{
	Account a1("bem", 42);
	cout << a1.balance() << endl;
	a1.calculate();
	cout << a1.balance() << endl;

	return 0;
}

在这里插入图片描述

成员定义的作用域的查找

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7.5、构造函数再探

构造函数初始化列表

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

隐式类类型转换

在这里插入图片描述
在这里插入图片描述

explicit

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

聚合类

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

字面值常量

在这里插入图片描述
在这里插入图片描述

constexptr构造函数

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7.6、类的静态成员

在这里插入图片描述

#include "Version_test.h"

#ifndef ACCOUNT_H
#define ACCOUNT_H

#include <string>

class Account {
public:
#if defined(DEFAULT_FCNS) && defined(IN_CLASS_INITS)
	Account() = default;
#else
	Account(): amount(0.0) { }
#endif
	Account(const std::string &s, double amt):
		owner(s), amount(amt) { }

    void calculate() { amount += amount * interestRate; }
    double balance() { return amount; }
public:
    static double rate() { return interestRate; }
    static void rate(double);   
private:
    std::string owner; 
#ifdef IN_CLASS_INITS
    double amount = 0.0; 
#else
	double amount;
#endif
    static double interestRate; 
    static double initRate() { return .0225; }
    static const std::string accountType;
#ifdef CONSTEXPR_VARS
    static constexpr int period = 30;// period is a constant expression
#else
	static const int period = 30;// period is a constant expression
#endif
    double daily_tbl[period];
};
#endif
#include <string>
using std::string;

#include "Account.h"

// define static data and function members
const string Account::accountType("Savings Account");
double Account::interestRate = initRate();

void Account::rate(double newRate) 
{
    interestRate = newRate; 
}
#include <iostream>
using std::cout; using std::endl;

#include <string>
using std::string;

#include "Account.h"

int main()
{
	Account a1("bem", 42);
	cout << a1.balance() << endl;
	a1.calculate();
	cout << a1.balance() << endl;

	return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

定义静态成员

#include "Version_test.h"

#include "Debug.h"
// only implementation for the Debug classes are definitions
// for static members named enable 
#ifdef CONSTEXPR_CTORS
constexpr Debug HW_Subsystem::enable;
constexpr Debug IO_Subsystem::enable;
#else
const Debug HW_Subsystem::enable(true, false, false);
const Debug IO_Subsystem::enable(true, false, true);
#endif
#include "Version_test.h"

#include <iostream>
using std::cerr; using std::endl;

#include "Debug.h"

int main()
{
#ifdef CONSTEXPR_VARS
	constexpr Debug io_sub(false, true, false);  // debugging IO    
#else
	const     Debug io_sub(false, true, false);  // debugging IO    
#endif
	if (io_sub.any())  // equivalent to if(true)
		cerr << "print appropriate error messages" << endl;

#ifdef CONSTEXPR_VARS
	constexpr Debug prod(false); // no debugging during production
#else
	const     Debug prod(false); // no debugging during production
#endif
	if (prod.any())    // equivalent to if(false)
		cerr << "print an error message" << endl;

	IO_Subsystem ioErrs;        // by default, don't print any debugging
	// no debugging here
	if (ioErrs.default_debug()) // if (false || debug.any())
		cerr << "print message 3" << endl;
	ioErrs.set_debug(true);     // turn on debugging
	if (ioErrs.default_debug()) // if (false || debug.any())
		cerr << "print message 4" << endl;
	ioErrs.set_debug(false);    // okay, debugging section complete

	HW_Subsystem hw;
	hw.set_debug(true);
	if (ioErrs.default_debug() || hw.default_debug()) // if (false || debug.any())
		cerr << "print message 5" << endl;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7.7、小结

在这里插入图片描述

7.8、术语表

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值