• 关于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:类的更多相关文章

  1. Chapter7(类) --C++Prime笔记

    类(关键词):数据抽象(数据成员和函数成员),封装(private),构造函数,静态成员 1.判断一个类是否是抽象数据类型,可以看我们对这个类的操作是对你内的数据成员操作,自己编写相应的处理函数,还是 ...

  2. Java类的继承与多态特性-入门笔记

    相信对于继承和多态的概念性我就不在怎么解释啦!不管你是.Net还是Java面向对象编程都是比不缺少一堂课~~Net如此Java亦也有同样的思想成分包含其中. 继承,多态,封装是Java面向对象的3大特 ...

  3. ###《Effective STL》--Chapter7

    点击查看Evernote原文. #@author: gr #@date: 2014-08-31 #@email: forgerui@gmail.com Chapter7 在程序中使用STL Topic ...

  4. (六)《Java编程思想》——初始化及类的加载顺序

    package chapter7; /** * 初始化及类的加载顺序:顺序如下 * 1.基类的static变量 * 2.导出类的static变量 * 3.基类的变量 * 4.基类的构造函数 * 5.导 ...

  5. 开涛spring3(7.2) - 对JDBC的支持 之 7.2 JDBC模板类

    7.2  JDBC模板类 7.2.1  概述 Spring JDBC抽象框架core包提供了JDBC模板类,其中JdbcTemplate是core包的核心类,所以其他模板类都是基于它封装完成的,JDB ...

  6. python cookbook第三版学习笔记十二:类和对象(三)创建新的类或实例属性

    先介绍几个类中的应用__getattr__,__setattr__,__get__,__set__,__getattribute__,. __getattr__:当在类中找不到attribute的时候 ...

  7. (转)JDBC模板类。

    Spring JDBC抽象框架core包提供了JDBC模板类,其中JdbcTemplate是core包的核心类,所以其他模板类都是基于它封装完成的,JDBC模板类是第一种工作模式. JdbcTempl ...

  8. spring3:对JDBC的支持 之 JDBC模板类

    7.2  JDBC模板类 7.2.1  概述 Spring JDBC抽象框架core包提供了JDBC模板类,其中JdbcTemplate是core包的核心类,所以其他模板类都是基于它封装完成的,JDB ...

  9. synchronized的对象锁和类锁

    概念 synchronized 是 Java 中的关键字,是利用锁的机制来实现同步的. 锁机制有如下两种特性: 互斥性:即在同一时间只允许一个线程持有某个对象锁,通过这种特性来实现多线程中的协调机制, ...

随机推荐

  1. 【资料分享】 OpenCV精华收藏

    OpenCV精华收藏 SkySeraph Dec.29th 2010  HQU Email:zgzhaobo@gmail.com    QQ:452728574 Latest Modified Dat ...

  2. emacs 快捷键笔记

    C-d C-aM-aC-eM-e===复制黏贴M-d    kill-wordM-del     backward-kill-wordM-k     kill-sentenceC-x del back ...

  3. flex Bindable

    [Bindable]大概又是Flex用得最多的元数据了.刚开始用用确实好简单,效率真是没的说.不过这几天用着却碰到了些问题,我自己搜集了些资料,想着有必要在blog里总结一下吧. 啥是元数据(meta ...

  4. env1

    给新手参考的Cadence Allegro快捷键 原文链接:http://www.eda365.com/thread-30935-1-1.html 发上我的快捷键给新手参考,我也是在LULU给我的EN ...

  5. 如何从List<T>中筛选符合条件的数据的集合或个数

    方法一:Linq ChannelList就是一个List类型的数据,IsOpen 是其元素的属性 channelCount = (from channel in DevicesManager.Inst ...

  6. 好!maximum-product-of-word-lengths

    以后看到个数比较少,性能比较高,就要第一时间想到位操作! 这道题目mock没有通过.超时了...... 原来题目解法的思路非常非常好! 开始我关注于降低n*n的复杂度,但是这道题目复杂度高在每个字符串 ...

  7. C#配置系统未能初始化

    如果配置文件中包含 configSections 元素,则 configSections 元素必须是 configuration 元素的第一个子元素.",将appSettings放到conf ...

  8. poj 3353 Road Construction tarjan 边双联通分支 缩点+结论

    题意:一个连通的无向图,求至少需要添加几条边,救能保证删除任意一条边,图仍然是连通的. 链接:http://poj.org/problem?id=3352 思路:边的双连通图.其实就是要求至少添加几条 ...

  9. MVC+Ef项目(2) 如何更改项目的生成顺序;数据库访问层Repository仓储层的实现

    我们现在先来看看数据库的生成顺序   居然是 Idal层排在第一,而 web层在第二,model层反而在第三 了   我们需要把 coomon 公用层放在第一,Model层放在第二,接下来是 Idal ...

  10. LeetCode Valid Number 有效数字(有限自动机)

    题意:判断一个字符串是否是一个合法的数字,包括正负浮点数和整形. 思路:有限自动机可以做,画个图再写程序就可以解决啦,只是实现起来代码的长短而已. 下面取巧来解决,分情况讨论: (1)整数 (2)浮点 ...