文章目录
一、概述
二、内容
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、术语表