当前位置: 首页 > news >正文

c++ primer 阅读手记 第七章

1、定义在类内部的函数式隐式的inline函数;

2、常量成员函数

//使用const在类内部声明定义常量成员函数,bookNo:成员变量
std::string isbn() const { return bookNo; }

  常量成员函数不会修改类的成员变量,也不能调用任何非常量成员函数;
  常量对象,以及常量对象的引用或指针都只能调用常量成员函数;

3、编译器分两步处理类:首先编译成员的声明,然后才是成员的函数体(如果有)。因此,成员函数体和类中的其他成员没有次序的影响;

4、一般来说,如果非成员函数是类接口的组成部分,则这些函数的声明应该与类在同一个头文件内。

5、类可以包含多个构造函数,和其他重载函数差不多。构造函数不能被声明成const。

6、某些类不能依赖于合成的默认构造函数:建议自已定义构造函数!
  C++新标准中,可以自己定义默认构造函数:

//构造函数Sales_data()
Sales_data() = default;  //在自定义多个构造函数时,保留不自定义构造函数时合成的默认构造函数

7、构造函数初始值列表

//构造函数初始值列表初始化成员时,并不一定按照列表顺序进行,这里不建议使用成员初始化成员。
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(const std::string &s) : bookNo(s),units_sold(0), revenue(0) {}

//构造函数比较草率的写法,不使用构造函数初始值
Sales_data::Sales_data(const string &s,unsigned cnt)
{
	bookNo = s;
	units_sold = cnt;
}

//如果成员是const、引用,或属于某种未提供默认构造函数的类类型,必须通过构造函数初始值列表为这些成员提供初始值。
//建议:使用构造函数初始值

8、使用class或struct关键字
  这两个都能定义类,唯一区别是默认的访问权限不同;
  class:第一个访问说明符前的成员都是private;
  struct:第一个访问说明符前的成员都是publec;

9、友元:非类的成员函数若要访问类的private成员,则需要成为类的友元;
  关键字:friend

//友元声明只能在类定义的内部;友元声明并非通常意义上的函数声明,类的用户调用友元函数需要再专门进行函数声明。
class Sales_data {
friend std::istream &read();
...
};

//类之间的友元关系
class Screen{
friend class Window_mgr;   // Window_mgr 的成员可以访问Screen类的私有部分

//或令成员函数作为友元:friend void Window_mgr::clear();  
//Window_mgr::clear必须在Screen类之前被声明,但不能定义。
//因为要在clear中使用Screen的成员,所以定义clear之前要先定义Screen,包括对clear的友元声明,最后定义clear。

private:
	void fun();
}
class Window_mgr{
public:
void clear();
}
void Window_mgr::clear()
{
	Screen s;
	s.fun(); 
}

//每个类负责控制自己的友元类或友元函数

10、关键字:mutable

//类内声明
mutable size_t access_ctr;   //可变数据成员,即使在一个const对象内也能被修改

11、当我们提供一个类内初始值时,必须以符号=或者花括号表示。

12、返回*this的成员函数:函数返回类型为引用,则返回对象本身;函数返回类型非引用,则返回对象的副本。

13、一个const成员函数如果以引用的形式返回*this,那么它的返回类型将是常量引用。

14、基于const的重载

class Screen {
public:
//根据对象是否时const重载了display函数
Screen &display() {}
const Screen &display() const {}
}

15、类类型

Sales_data item1;  //默认初始化Sales_data类型的对象
class Sales_data item1; //一条等价的声明,从C语言继承而来

16、类的声明

class Screen;   //Screen类的声明,在定义之前是一个不完全类型,不能创建它的对象。

17、只有当类全部完成后类才算被定义,所以一个类的成员类型不能时该类自己,但声明过未定义的情况下,允许包含指向它自身类型的引用或指针:

class Link_screen {
Link_screen *next;
}

18、如果一个构造函数为所有参数都提供了默认实参,则它实际上也定义了默认构造函数。

Sales_data(std::string s = "") : bookNo(s) { }

19、委托构造函数

class Sales_data
{
public:
    std::string bookNo = "0";
    unsigned units_sold = 0;
    double revenue = 0;

    // 非委托构造函数使用对应的实参初始化成员
    Sales_data(std::string s, unsigned cnt, double price) : bookNo(s), units_sold(cnt), revenue(cnt * price)
    { 
        std::cout << bookNo << "_0"<< std::endl;
    }
    // 其余构造函数全都委托给另一个构造函数
    Sales_data() : Sales_data("默认委托", 0, 0) // 定义默认构造函数,委托给了三参数的构造函数
    {
        std::cout << bookNo << "_1" << std::endl;
    } 
    Sales_data(std::string s) : Sales_data(s, 0, 0) //这种委托能传递形参的值
    { 
        std::cout << s  << "_2" << std::endl; 
        std::cout << bookNo  << "_2" << std::endl; 
    }
    Sales_data(float ff) : Sales_data() //这种套娃式委托,由最先被委托的构造函数一层一层执行
    { 
        std::cout << bookNo  << "_3" << std::endl; 
        std::cout << ff  << "_3" << std::endl; 
    }

};

int main(int argc, char *argv[])
{
    Sales_data test_Sales;
    Sales_data test_Sales_single("单参数构造函数");
    Sales_data test_Sales_float(0.232);
    return 0;
}
/*从运行结果能看出委托构造函数的执行顺序,运行结果如下:
默认委托_0
默认委托_1
单参数构造函数_0
单参数构造函数_2
单参数构造函数_2
默认委托_0
默认委托_1
默认委托_3
0.232_3
*/
		

20、

Sales_data obj(); // 声明了一个函数而非对象
Sales_data obj2; // obj2是一个对象

21、隐式的类类型转换

22、聚合类,同时满足以下条件:
  a,所有成员都是public的;
  b,没有定义任何构造函数;
  c,没有类内初始值;
  d,没有基类,也没有virtuall函数。

struct Data {
	int ival;
	string s;
};
//可以使用花括号初始化数据成员,val1.ival = 0; val1.s = string("Anna")
Data val1 = { 0, "Anna" };
//初始值顺序必须与声明顺序一致,初始值列表的元素个数可以少于类成员数量,优先初始化靠前的元素,但不能多。

23、字面值常量类

24、类的静态成员
  存在的意义:这些成员与类本身有直接关系,但与类的对象没有关联;
  声明方式:成员声明前加上关键字static。可以是public或private,类型可以是常量、引用、指针、类类型等。
  不与任何对象绑定,故没有this指针,进而静态成员函数不能声明成const的,函数体内不能使用this指针。

double r;
r = Account::rate();  //使用作用域运算符访问静态成员
//也可使用类的对象、引用或指针来访问静态成员
//成员函数不用通过作用域运算符就能直接使用静态成员

  静态成员的关键字static只出现在类内部的声明语句,静态成员函数的定义和其他成员函数一样。
  静态数据成员不属于类的任何对象,也就不是创建类的对象时被定义初始化的,也就不是由类的构造函数初始化的。必须在类外定义和初始化每个静态成员,且只能定义一次。类似全局变量,一旦被定义,将存在于程序的整个生命周期中。

double Account::interestRate = initRate();  //定义并初始化一个静态成员,声明在类内部

25、静态成员的类内初始化:通常也应该在类的外部定义一下该成员

//类内部
static constexpr int period = 30; //period 是常量表达式
double daily_tbl[period];

//类外部
constexpr int Account::period;    //一个不带初始值的静态成员的定义,初始值在类的定义内提供

26、静态成员能用于某些场景,而普通成员不能

class Bar{
	//静态数据成员可以时不完全类型
	static Bar mem1; //正确
	Bar *mem2; // 正确
	Bar mem3; //错误
	
	//静态成员可以作为默认实参
	Bar& clear(char = bk);
	static const char bk;
};

相关文章:

  • 【蓝桥杯】 枚举和模拟练习题
  • 统一语言学习范式
  • 企业级海外网络专线行业应用案例及服务商推荐
  • element-ui图片查看器
  • idea导入tomcat的jar
  • 算法学习11——滑动窗口——最大连续1的个数
  • 兼职网|基于Java+vue的兼职网系统(源码+数据库+文档)
  • 交换机、路由器、VLAN、单臂路由、三层交换、STP
  • python学习笔记(6)运算符
  • 蓝桥杯—日期遍历
  • 1. 两数之和
  • 美颜SDK兼容性挑战:如何让美颜滤镜API适配iOS与安卓?
  • 2025宁德时代测评Verify考什么?网申测评如何通过SHL笔试|附真题线上笔试考点、高分攻略、CATL新能源科技SHL测评宁德社招题目、面试攻略、求职建议
  • 华为MPLS Virtual PN option C1(有/无RR)配置wireshark抓包分析
  • AgGridReact 禁止checkbox复选框选中(isRowSelectable)
  • uniapp实现小票打印 兼容微信小程序安卓
  • 数据结构和算法(十一)--图
  • 【开发问题记录】高德地图 Web 端开发详解:高德地图 API 最佳实践指南(安装、marker添加、逆向地理编码、实际业务案例实操)
  • 华为MPLS Virtual PN option A配置wireshark抓包分析
  • unidbg读写跟踪还原X-Gorgon
  • 广东智慧团建系统登录入口/宁波seo网络推广公司排名
  • 做动车哪个网站查/seo网络优化是什么意思
  • 深圳做网站哪个好/信阳网站推广公司
  • 怀化找什么人做网站/百度提交入口网址
  • wordpress安装点提交无法访问/seo排名优化首页
  • 地级市政府网站建设评估/安装百度到手机桌面