c++ primer 读书笔记 之第七章类
来源:互联网 发布:2016全国溺水事故数据 编辑:程序博客网 时间:2024/05/16 01:44
只读书不记录总感觉没读,只记录不实践总感觉没记
接口代码例子:
struct Sales_data{ // 以下4个函数都是构造函数Sales_data():units_sold(0), revenue(0.0){ }Sales_data(const std::string &s): bookNo(s), units_sold(0), revenue(0.0) { }Sales_data(const std::string &s, unsigned n, double p): bookNo(s), units_sold(n), revenue(p*n) { }Sales_data(std::istream &);//绿色部分初始化列表,没在其中的的成员变量将执行隐式初始化,也就是说,该构造函数体内部其实更像是赋值,而不是初始化// 接口部分的成员函数,定义在类内部的函数都是隐式的inline函数std::string isbn() const { return bookNo; }//1、inline 函数;2、同时又是常量成员函数 ;3、成员函数体内可以随意适用其他成员变量或者成员函数,无需 在意声明的次序,因编译类时首先是编译成员的声明,然后才是成员函数体Sales_data& combine(const Sales_data&);double avg_price() const;std::string bookNo;unsigned units_sold;double revenue;};// 接口部分的非成员函数,想一想这些函数的调用者是对象吗?如果非成员函数是类接口的一部分,则这些函数的声明应该与类在同一个头文件内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_price() const {if (units_sold)return revenue/units_sold;elsereturn 0;}// 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'' objectreturn *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 sumsum.combine(rhs); // add data members from rhs into sumreturn sum;}// transactions contain ISBN, number of copies sold, and sales priceistream& read(istream &is, Sales_data &item)//同常我们为了避免copy值传递的效率低下,适用引用来作为形参,这是一种<优化技巧>但对于io类型的形参来说则是必 须,因为io类型的变量无copy类型{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;}Sales_data::Sales_data(std::istream &is) {// read will read a transaction from is into this objectread(is, *this);//先声明一下,this是一个指针,见<c++ primer>p231用请求该函数的对象地址来初始化this,以及this->bookNo。明白了所以*就是一个正常的普 通对象变量,为什么这里的实参是一个变量,而形参可以看到是一个引用。这就涉及到<函数胡形参>}inline函数适用条件:1.规模较小(能够在类内定义估计也不能太大);2.直接;3.重复使用(inline函数效率高,可以作为一种优化技巧)隐式inlien:定义在类内部胡函数;显式inline关键字inlie可以加在函数声明胡地方,也可以加在函数定义的地方,或者两者同时加,也不错。但一般是定义。还有就是inline函数的定义及时不能定义在类内,一般也要建议定义在头文件内。常量成员函数为了c++程序的健壮性。对于调用自身对象成员变量或者成员函数的成员函数,都应该声明为常量成员函数。因为对于这类成员函数,都隐式或者显式的适用。this来指代自身对象,自身对象有可能是常量对象也有可能是非常量对象,const来修饰this就可以做到万无一失。但是常量成员函数有一个缺点:在该函数内无法修改对象的成员变量,因为对象是const。下文提到的可变成员变量可以解决这一问题。对于即使在常量成员函数中你也想改变的成员变量,可以把它声明为mutable(可变成员变量)左值可以放在等号的左侧被赋值的值即为左值。(1)(a=1)=2 ok a=1=2 不ok。式子1是因为=源码返回的是一个引用(不信可以去看),所以可以作为左值。而式子2不行是因为c++中的赋值运算满足右结合律。构造函数只有当类没有声明任何构造函数时,编译器才会自动的生成默认构造函数。当然用户自己定义的构造函数也可以是默认构造函数。函数的传参
c++中,函数的传参只有两种值传递和引用传递(没错是没有指针这么一说的,但指针传递是划分为值传递中的)
A、 值传递(感觉称之为copy传递更好):普通变量值传递1、变量定义 int a=1;2、函数声明 int f(int val);3、 函数调用 f(a);
指针变量值传递 1、变量定义 int a=1; 2、函数声明 int f(int * val);3、函数调用f(&a)
B、引用传递:1、变量定义 int a=1;2、函数声明 int f(int & val);3、函数调用f(a)
总结:引用传递会带来两个方面的影响。1不用copy一份变量,节省时间和内存;2.是可以通过函数来改变实参。如果函数无须改变引用形参的值,最好将其声明为const,这样好像立了一个法,从法律上规定在函数体内部改变实参是违法的,让函数的使用者一目了然更加放心。为了软件的优化,会看到c++程序中(常量)引用漫天飞舞
符:引用还有一个技巧:当希望程序返回多于两个值时,一:用类等较复杂的抽象数据类型;二:将多于的返回值以引用的形式输入,同时获得。
上面代码阐述完毕,看下面一段代码:
class Sales_data {//改动1friend Sales_data add(const Sales_data&, const Sales_data&);//改动3friend std::ostream &print(std::ostream&, const Sales_data&);//改动3friend std::istream &read(std::istream&, Sales_data&);//改动3public: //改动2// constructorsSales_data(): units_sold(0), revenue(0.0) { }Sales_data(const std::string &s): bookNo(s), units_sold(0), revenue(0.0) { }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 objectsstd::string isbn() const { return bookNo; }Sales_data& combine(const Sales_data&);double avg_price() const;private: //改动2std::string bookNo;unsigned units_sold;double revenue;};// nonmember Sales_data interface functionsSales_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 chaptersinline bool compareIsbn(const Sales_data &lhs, const Sales_data &rhs){return lhs.isbn() < rhs.isbn();}上述代码与之前版本代码在大部分不变的情况下,有如下小的改动:
改动1:类的定义由struct 取代为class。两者唯一的区别是:struct的默认访问权限为public,class为private(更安全有没有)
改动2:构造函数和部分类内函数的访问说明符为public(整个程序都可访问);类内成员变量的访问说明符为private(类内可访问)。这就是c++的封装通过访问说明符来实现 这一机制。
改动3:有了改动2,那么其他想访问类内private变量的方法,怎么办呢?最直接的是最初版本代码中的add,print,read,(我们可是团结合作来实现一个接口的,连我都不不能信息 共享了),有两种方法,一种是类针对all想访问private的用户设计一个public函数,get_xx,set_xx。但在这些函数内部加以限制和判断。第二种方法是专门为朋友开后门, 也即友元。住:类内的friend声明仅仅是给类看的,类外还需正常的函数声明。类内友元声明,并不表明友元函数式类内函数。
类型成员给类型起别名:方式1:typedef std::string::size_type pos方式2:using pos=std::string::size_type
类型成员作为类成员的一种也是有访问修饰符public和private的。并且也注意:类型成员的定义必须位于使用之前重载成员函数成员函数参数的数量和类型有区别即可。可变数据成员见上文中的常量成员函数返回*this的成员函数
- c++ primer 读书笔记 之第七章类
- C++Primer读书笔记(第七章)
- 第七章 类 c++primer
- 《C++primer(第五版)》学习之路-第七章:类
- C++primer 第七章
- C++Primer第七章:类(学习摘录)
- c++primer第七章类小结-7
- 菜狗的C++ primer读书笔记:第七章 类
- 读书笔记《C++ Primer》第五版——第七章 类
- C++ Primer 读书笔记 – 第七章
- C++ Primer 读书笔记 – 第七章
- C++ Primer 读书笔记 – 第七章
- c++ primer读书笔记-第七章 函数
- C++ primer 读书笔记 第七章 --函数
- 《C++ Primer》读书笔记——第七章
- C++Primer读书笔记之引用
- c primer plus 第七章
- c primer plus 第七章
- 模板偏特化 指针 模板萃取 指针
- Linux-用户及文件权限管理
- IP地址分类
- 53 WebGL将渲染图形贴到另一个物体上面
- 【0054】SQL复制表 INSERT INTO SELECT
- c++ primer 读书笔记 之第七章类
- Android单元测试(二):再来谈谈为什么
- 无锁队列的实现
- 快速排序
- Eclipse连接mysql数据库
- hdu2670
- Thymeleaf 之 内置对象、定义变量、URL参数及标签自定义属性
- 四大组件之Activity
- hdu 2795 billboard(线段树)