Chapter7:类
- 关于this指针
成员函数通过一个名为this的额外的隐式参数来访问调用它的对象。当我们调用一个成员函数时,用请求该函数的对象初始化this。
total.isbn();
//等价于编译器重写为
Sale_data::isbn(&total);
因为this的目的总是指向“这个”对象,所以this是一个常量指针,我们不允许改变this中保存的地址。
例如this的类型是Sale_data* const。但是this需要遵守初始化规则,所以我们不能把this绑定到一个常量对象。也即:我们不能在一个常量对象上调用普通的成员函数。
为了解决这一问题,引入了常量成员函数,即在成员函数之后加const。
常量对象、常量对象的引用或指针都只能调用常量成员函数。
- 类作用域
类作用域的特点是:编译器分两步来处理:首先编译成员的声明,然后才轮到成员函数体。因此,成员函数体可以随意使用类中的其他成员而无须在意这些成员出现的次序。
类型名要特殊处理。在类中,如果成员使用了外层作用域中的某个名字,而该名字代表一种类型,则类不能在之后重新定义该名字。因此:类型名定义应该出现在类的开始处。
typedef double Money;
class Account
{
public:
Money balance() { return bal; }
private:
typedef double Money; //错误:不能重新定义Money
Money bal;
}; typedef double Money;
class Account
{
typedef double Money; //可以
public:
Money balance() { return bal; }
private:
Money bal;
};
类的作者常常需要定义一些辅助函数,比如add、read、print。尽管这些函数定义的操作从概念上来说属于类的接口组成部分,但它们实际上并不属于类的本身。(因为类本身的话,会附加this参数)
istream &read(istream &is, Sale_data &item)
{
;
}
ostream &print(ostream &os, const Sale_data &item)
{
;//print函数不负责换行,一般来说执行输出任务的函数应该尽量减少对格式的控制,由用户代码确定是否换行。
}
- 构造函数
构造函数不能声明为const,当我们创建类的一个const对象时,直到构造函数完成初始化过程,对象才能真正取得“常量”属性。
如果我们的类没有显式地定义构造函数,那么编译器就会为我们隐式地定义一个默认构造函数。
合成的默认构造函数:1)如果存在类内的初始值,用它来初始化成员;2)否则,默认初始化该成员。
对于一个普通的类来说,必须定义它自己的默认构造函数,原因有三
1)编译器只有在发现类不包含任何构造函数的情况下才会替我们生成一个默认构造函数;
2)合成的默认构造函数可能执行错误的操作。回忆之前:在块中定义的内置类型或复合类型的对象被默认初始化,则它们的值将是未定义的。
3)有时候编译器不能为某些类合成默认的构造函数。
=default
我们定义此构造函数的目的仅仅是因为我们既需要其他形式的构造函数,也需要默认的构造函数。
构造函数初始化列表
当某个数据成员被构造函数初始化列表忽略时,它将以与合成默认构造函数相同的方式隐式初始化(在函数体执行之前)。
成员初始化的顺序与它们在类定义中的顺序一致。所以,Best Practice:初始值列表最好与成员声明顺序一致。
C++11委托构造函数
- 类类型转换
我们可以为类定义隐式转换规则。如果构造函数只接受一个实参,则它实际上定义了次类类型的隐式转换机制。切记:只允许一步类类型转换。
使用explicit抑制隐式转换:
explicit只能在类内声明构造函数时使用,在类外部定义时不应该重复。
explicit只能用于直接初始化,不能用于拷贝初始化。
Sale_data item1(null_data);//正确
Sale_data item2=null_data;//错误
explicit可以显式转换
item.combine(Sale_data(null_book));
item.combine(static_cast<Sale_data>(cin))
- 聚合类:可以使用花括号成员初始值列表
所以成员都是public
没有定义构造函数
没有类内初始值
没有基类,没有virtual
- 字面值常量类:
数据类型都是字面值类型的聚合类是字面值常量类,或者符合下述条件的类:
1)数据类型都是字面值类型;
2)至少有一个constexpr构造函数;
3)数据成员:内置类型的初始值必须是常量表达式;类类型初始值必须使用constexpr构造函数;
4)类必须使用默认的析构函数
- 类的静态成员
静态成员函数不与任何对象绑定在一起,即:不能使用this指针,不能声明为const。
当在类外部定义静态成员时,不能重复static关键字;因为不属于对象,所以不是由构造函数中初始化:需要在类的外部定义和初始化每个静态成员。
class Account
{
static double interestRate;
};
double Account::interestRate = ;
当静态成员是const的时候,可以在类内提供初始值。此时,也应该在类外定义一下该成员。
class Account
{
static constexpr double interestRate = 0.8;
};
constexpr double Account::interestRate;
静态成员可以是不完全类型;可以做默认实参。非静态成员不能做默认实参,因为它值本身是对象的一部分,所以无法真正提供一个对象以便从中获取成员的值。
- 友元
如果类想把一个函数作为它的友元,只需要增加一条以friend关键字开始的函数声明即可。
友元的声明仅仅是指定了访问权限,而非一个通常意义上的函数声明。如果希望调用某个友元函数,那么必须在友元声明之外再专门对函数进行一次声明。
(许多编译器并未强制限定友元函数必须在使用之前在类的外部声明)
令成员函数为友元
需要仔细组织程序结构以满足声明和定义的彼此依赖关系。
class Window_mgr
{
public:
void clear(); };
class Screen
{
//不同于普通函数,之前必须声明
friend void Window_mgr::clear();
}; //Screen定义后,再定义clear函数,因为要用到Screen
void Window_mgr::clear()
{
Screen s;
}
类和非成员函数的声明不是必须在它们的友元声明之前。当一个名字第一次出现在一个友元声明中时,我们隐式地假定该名字在当前作用域中可见。
class X
{
public:
friend void f() {/*定义f*/; }
X() { f(); }//错误,f还没有声明
void g();
}; void X::g() { f(); }//错误,f还没有声明
void f();//声明那个定义在X中的函数
void X::g() { f(); }//正确
类的声明
在声明之后定义之前,类是一个不完全类型。只能在有限情况下使用:
1)可以定义指向这种类型的引用或指针;2)可以声明(但不能定义)以不完全类型作为参数或者返回类型的函数。
Chapter7:类的更多相关文章
- Chapter7(类) --C++Prime笔记
类(关键词):数据抽象(数据成员和函数成员),封装(private),构造函数,静态成员 1.判断一个类是否是抽象数据类型,可以看我们对这个类的操作是对你内的数据成员操作,自己编写相应的处理函数,还是 ...
- Java类的继承与多态特性-入门笔记
相信对于继承和多态的概念性我就不在怎么解释啦!不管你是.Net还是Java面向对象编程都是比不缺少一堂课~~Net如此Java亦也有同样的思想成分包含其中. 继承,多态,封装是Java面向对象的3大特 ...
- ###《Effective STL》--Chapter7
点击查看Evernote原文. #@author: gr #@date: 2014-08-31 #@email: forgerui@gmail.com Chapter7 在程序中使用STL Topic ...
- (六)《Java编程思想》——初始化及类的加载顺序
package chapter7; /** * 初始化及类的加载顺序:顺序如下 * 1.基类的static变量 * 2.导出类的static变量 * 3.基类的变量 * 4.基类的构造函数 * 5.导 ...
- 开涛spring3(7.2) - 对JDBC的支持 之 7.2 JDBC模板类
7.2 JDBC模板类 7.2.1 概述 Spring JDBC抽象框架core包提供了JDBC模板类,其中JdbcTemplate是core包的核心类,所以其他模板类都是基于它封装完成的,JDB ...
- python cookbook第三版学习笔记十二:类和对象(三)创建新的类或实例属性
先介绍几个类中的应用__getattr__,__setattr__,__get__,__set__,__getattribute__,. __getattr__:当在类中找不到attribute的时候 ...
- (转)JDBC模板类。
Spring JDBC抽象框架core包提供了JDBC模板类,其中JdbcTemplate是core包的核心类,所以其他模板类都是基于它封装完成的,JDBC模板类是第一种工作模式. JdbcTempl ...
- spring3:对JDBC的支持 之 JDBC模板类
7.2 JDBC模板类 7.2.1 概述 Spring JDBC抽象框架core包提供了JDBC模板类,其中JdbcTemplate是core包的核心类,所以其他模板类都是基于它封装完成的,JDB ...
- synchronized的对象锁和类锁
概念 synchronized 是 Java 中的关键字,是利用锁的机制来实现同步的. 锁机制有如下两种特性: 互斥性:即在同一时间只允许一个线程持有某个对象锁,通过这种特性来实现多线程中的协调机制, ...
随机推荐
- android学习系列:jercy——AI3 的博客
[android学习之十七]——特色功能2:桌面组件(快捷方式,实时文件夹) 二.桌面组件 1.快捷方式 Android手机上得快捷方式的意思可以以我们实际PC机器上程序的快捷方式来理解.而andro ...
- Debugging JTAG Connectivity Problems
2013-12-04 22:34:26 转自:http://processors.wiki.ti.com/index.php/Debugging_JTAG_Connectivity_Problems ...
- 标准类型内建函数 cmp()介绍
内建函数cmp()用于比较两个对象obj1 和obj2, 如果obj1 小于obj2, 则返回一个负整数,如果obj1 大于obj2 则返回一个正整数, 如果obj1 等于obj2, 则返回0.它的行 ...
- JQuery_给元素添加或删除类等以及CSS()方法
一.addClass() - 向被选元素添加一个或多个类 <script src="jquery-1.11.1.min.js"></script> < ...
- EASYUI+MVC4通用权限管理平台--前言
经过多年的管理信息系统的开发工作,吸取了工作中遇到的一些问题,经过自己的总结,形成了一套比较完整的管理信息系统的通用权限管理基础开发平台. 在软件的开发过程中我们首先需要解决的是UI问题,其次是浏览器 ...
- factory工厂模式
工厂方法模式 工厂方法模式概述 工厂方法模式中抽象工厂类负责定义创建对象的接口,具体对象的创建工作由继承抽象工厂的具体类实现 简单理解: 与简单工厂模式类似,简单工厂模式是一个工厂,用户将条件为 ...
- UVALive 3989 Ladies' Choice(稳定婚姻问题:稳定匹配、合作博弈)
题意:男女各n人,进行婚配,对于每个人来说,所有异性都存在优先次序,即最喜欢某人,其次喜欢某人...输出一个稳定婚配方案.所谓稳定,就是指未结婚的一对异性,彼此喜欢对方的程度都胜过自己的另一半,那么这 ...
- Typed Message模式与Event Sourcing
引言 在<设计模式沉思录>(Pattern Hatching: Design Patterns Applied,[美]JohnVlissides著)一书的第4章中,围绕事件Message传 ...
- 【量化】docker
查看docker docker ps docker ps -a 删除docker docker stop 8809752ca95a docker rm 8809752ca95a 打包fly cd ~/ ...
- linux中备份mysql数据库的一个shell脚本
#!/bin/bash #FileName:select_into_bak.sh #Desc:Use select into outfile to backup db or tables #Creat ...