//7.1定义数据类型
//7.1.1设计Sales_data类
//7.1.2定义改进的sales_data类
#include "iostream"
#include "string"
using namespace std;
struct 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&);
//引入this
//观察isbn成员函数的调用
//total.isbn();
//在这力我们使用了点运算符来访问total对象的isbn成员,然后调用它。
//引入const成员函数
//类作用域和成员函数
//在类的外部定义成员函数
//定义一个返回this对象的函数
//7.1.3定义类相关的非成员函数
//类的作者常常需要定义一些辅助函数,比如add、read和print等。
//尽管这些函数定义的操作从概念上来说属于类的接口的组成部分,但它们实际上并不属于类本身
//我们定义非成员函数的方式与定义其他函数一样,通常把函数的声明和定义分离开来。如果函数在概念
//上属于类但是不定义在类中,则它一般应与类声明(而非定义)在同一个头文件内。在这种方式下,用户使用接口的任何部分都只需要引入一个文件。
//定义read和print函数
//定义add函数和print函数与2.6.2节中的代码作用一样,而且代码本身也非常相似
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;
}
//定义add函数
//add函数接受两个sale_data对象作为其参数,返回值是一个新的sales_data,用于表示前两个对象的和:
Sales_data add(const Sales_data &lhs, const Sales_data &rhs) {
Sales_data sum = lhs;
sum.combine(rhs); //把rhs的数据成员加到sum当中。
return sum;
}
//7.1.4构造函数
//合成的默认构造函数
//某些类不能依赖于合成的默认构造函数
//构造函数初始值列表
//在类的外部定义构造函数
//7.1.5拷贝、赋值和析构
//某些类不能依赖于合成的版本
//7.2访问控制与封装
//定义在public说明符之后的成员在整个程序内可悲访问,public成员定义类的接口
//定义在private说明符之后的成员可以被类的成员函数访问,但是不能被使用该类的代码访问
//private部分封装了类的实现细节。
//使用class和struct关键字
//唯一区别是默认的访问权限。
//7.2.1 友元
//既然,sales_data的数据成员是private的,我们的read、print和add函数也就无法正常编译了,
//这是因为尽管这几个函数是类的接口的一部分,但他们不是类的成员
//类可以允许其他类或者函数访问它的非公有成员,方法是零其他类或者函数成为它的友元。如果想把一个函数作为
//它的友元,只需要增加一条以关键字friend开始的函数声明语句即可。
//友元声明只能出现在类定义的内部,但是在类内出现的具体位置不限。友元不是类的成员也不受它所在区域访问控制级别的约束。
//7.3类的其他特性
//7.3.1类成员再探
//定义一个类型成员
//class Screen
//{
//public:
// typedef std::string::size_type pos;
//
//
//private:
// pos cursor = 0;//光标位置
// pos height = 0, width = 0;//屏幕尺寸
// std::string contents;
//};
//Screen类的成员函数
//要使我们的类更加实用,还需要添加一个构造函数令用户能够定义屏幕的尺寸和内容,以及其他两个成员
//分别负责移动光标和读取给定位置的字符:
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);//能在之后被设置位内联
private:
pos cursor = 0;//光标位置
pos height = 0, width = 0;//屏幕尺寸
std::string contents;
};
//令成员作为内联函数
//在类中,常有一些规模较小的函数适合于被声明成内联函数。如我们之前所见的,定义在类内部的成员函数
//是自动inline的。因此screen的构造函数和返回光标所指字符的get函数默认是inline的
//我们可以在类的内部把inline作为声明的一部分显式地声明成员函数,同样,也可以在类的外部用inline关键字修饰函数的定义:
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];
}
//虽然我们无须再声明和定义的地方同时说明inline,但这么做其实是合法的。不过,
//最好再类外部定义的地方说明inline,这样可以使类更容易理解。
//重载成员函数
//和非成员函数一样,成员函数也可以被重载(参见6.4节,第206页),只要函数之间再参数的数量和/或类型上有所区别就行。
//可变数据成员
//有时,会发生这样一种情况,我们希望能修改类地某个数据成员,即使是在一个const成员函数内。可以通过在变量的声明中假如mutale关键字做到这一代你。
//一个可变的数据成员永远不会是const,即使它是const对象的成员。
//7.3.2返回*this的成员函数
//7.3.3类类型
//7.3.4友元再探
//类还可以把其他的类定义成友元,也可以把其他类的成员函数定义成友元。此外,友元函数能定义在类的内部,这样的函数使隐式内联的。
//7.4类的作用域
//7.4.1名字查找与类的作用域
//7.5构造函数再探
//7.5.1构造函数的初始值列表
//构造函数的初始值有时必不可少
//成员初始化的顺序
//7.5.2委托构造函数
//7.5.3默认构造函数的作用
//7.5.4隐式的类类型转换
//7.5.5聚合类
//聚合类使得用户可以直接访问其成员,并且具有特殊的初始化语法形式。
//1.所有成员都是public的
//2.没有定义任何构造函数
//3.没有类初始值
//4.没有基类,也没有virtual函数
//如下:
struct data
{
int ival;
string s;
};
//7.5.6字面值常量类
//7.6类的静态成员
//有的时候需要他的一些成员与类本身直接相关,而不是与类的各个对象保持关联。
//例如:一个银行账户类可能需要一个数据成员来表示当前的基准利率。在此例中,我们希望利率与类关联,
//而非与类的每个对象关联。从实际效率来看,没有必要每个对象都存储利率信息。而且更加重要的是,一旦利率变动
//我们希望所有的对象都使用新值。
//声明静态成员
//我们通过在成员的声明之前加上关键字static使得其与类关联在一起。和其他成员一样,
//静态成员可以是public的或private的。静态数据成员的类型可以使常量、引用、指针、类类型等。
//example:
class Account
{
public:
void calcuatr() { amount += amount*interestRate; }
static double rate() {
return interestRate;
};
static void rate(double);
private:
std::string owner;
double amount;
static double interestRate;
static double initRate();
};
//注:静态成员函数也不与任何对象绑定在一起,他们不包含this指针。作为结果,静态成员函数不能声明成const的,而且我们也不能再static函数体
//内使用this指针。这一限制既适用于this的显式使用,也对调用非静态成员的隐式使用有效。
//使用类的静态成员
double r = Account::rate();
//定义静态成员
//静态成员的类内初始化
//静态成员能用于某些场景,而普通成员不能
C++Primer 学习笔记 第七章 类
最新推荐文章于 2024-08-21 18:16:36 发布
![](https://img-home.csdnimg.cn/images/20240711042549.png)