struct Sales_data {
//构造函数
Sales_data() = default;
Sales_data(const std::string &s):bookNo(s){}
Sales_data(const std::string &s,unsigned n,double p):
bookNo(s),units_sold(n),revenue(p*n){}
Sales_data(std::istream &);
//新成员:关于Sales_data对象的操作
std::string isbn() const {return bookNo;}
Sales_data &combine(const Sales_data&);
double avg_price() const;
//数据成员
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};
// Sales_data的非成员接口函数
Sales_data add(const Sales_data&,const Sales_data&);
std::ostream &print(std::ostream&,const Sales_data&);
std::istream &read(std::istream,Sales_data&);
常量对象,以及常量对象的引用或指针都只能调用常量成员函数
double Sales_data::avg_prise() 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;//返回调用该函数的对象
}
//调用:
total.combine(trans); //解引用得到total的引用
属于类接口的组成部分但不属于类本身
// IO类属于不能被拷贝的类,只能用引用方式
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;
}
控制对象的初始化过程,没有返回类型,
不能被声明成const,因为创建const对象时,知道构造函数完成初始化过程,对象才取得常量属性
合成的默认构造函数
=default
初始话列表
在类外部定义构造函数
Sales_data::Sales_data(std::istream &is){
read(is,*this);//从is中读取一条交易信息存入this中
}
class Sales_data {
public: //添加访问说明符
//构造函数
Sales_data() = default;
Sales_data(const std::string &s):bookNo(s){}
Sales_data(const std::string &s,unsigned n,double p):
bookNo(s),units_sold(n),revenue(p*n){}
Sales_data(std::istream &);
//新成员:关于Sales_data对象的操作
std::string isbn() const {return bookNo;}
Sales_data &combine(const Sales_data&);
private:
double avg_price() const
{return units_sold?revenue/units_sold:0;}
//数据成员
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};
// Sales_data的非成员接口函数
Sales_data add(const Sales_data&,const Sales_data&);
std::ostream &print(std::ostream&,const Sales_data&);
std::istream &read(std::istream,Sales_data&);
类可以允许其他类或函数访问它的非公有成员,方法是令其他类或函数成为它的友元
#ifndef _SCREEN_H
#define _SCREEN_H
#include
class Screen{
public:
// 必须先定义后使用
typedef std::string::size_type pos;
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; //显示内联
Screen &move(pos r,pos c); // 能在之后被设置为内联
// 类型别名,与上等价
// using pos = std::string size_type;
private:
pos cursor = 0;
pos height = 0, width = 0;
std::string contents;
};
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 //在类内声明成inline
{
pos row = r*width; //计算行的位置
return contents[row + c];//返回给定列字符
}
#endif
class Window_mgr{
std::vector screens{Screen(24,80,' ')};
};
符号=
或花括号
Sales_data item1;
class Sales_data item1; //等价声明,从C语言继承而来
class Screen; //前向声明,只声明不定义,不完全类型,可已指向这种类型的指针或引用,也可以声明以不完全类型为参数或者返回类型的函数
calss Screen{
// Window_mgr::clear 需要在之前被声明
friend void Window_mgr::clear(ScreenIndex);
}
甚至在类内部定义该函数,也必须在类外提供相应的声明
,换句话说,仅仅用声明友元函数的类的成员调用该友元函数,它也必须是被声明过的:struct X {
friend void f(){/*友元函数可以在类内部定义*/}
X(){f();} //错误,f还没被声明
void g();
void h();
}
void X::g(){return f();}//错误,f还没被声明
void f();
void X::h(){return f();}//正确,现在f的声明在作用域中了
有的编译器并不强制执行上述关于友元的限定
Screen::pos ht=24; //使用Screen定义的pos类型
class Sales_data {
public:
//非委托构造函数使用对应的实参初始化成员
Sales_data(std::string s,unsigned cnt,double price):
bookNo(s),units_sold(cnt),revenue(cnt*price){}
//其余构造函数全都委托给另一个构造函数
Sales_data():Sales_data("",0,0){}
Sales_data(std::string s):Sales_data(s,0,0){}
Sales_data(std::istream &is):Sales_data()
{read(is,*this);} //委托默认构造函数
}
item.combine("9-999-999"); //错误
item.combine(string("9-999-999")); //正确
class Sales_data{
explicit Sales_data(std::istream&);
}
item.combine(Sales_data(nukk_book));//正确
item.combine(static_cast<Sales_data>(cin));//正确
用户可以直接访问其成员,且具有特殊的初始化语法形式,类似C语言中的struct
struct Data{
int ival;
string s;
}
Data val={0,"Anna"};
class Debug{
public:
constexpr Debug(bool b=true):hw(b),io(b),other(b){} //必须初始化所有数据成员
...
}
有时候类需要一些成员与类本身相关,而非与类各个对象保持联系
class Account{
public:
void calculate(){amount += amount*interestRate;}//成员函数可以直接访问
static double rate(){return interestRate;}
static void rate(double);
private:
std::string owner;
double amount;
static double interestRate;
static double initRate();
}
//在外部定义静态成员时不能重复使用static关键字
void Account::rate(double newRate){
interestRate=newRate;
}
//定义并初始化静态成员
double Account::interestRate=initRate();
Account c1;
double r=Account::rate(); //使用作用域运算符访问静态成员
r=c1.rate(); //通过对象访问
class Account{
private:
static constexpr int period=30;
double daily_tbl[period];
}
//即使在类内初始化了,类外部也该定义一下
constexpr int Account::period;