1.在类内部,声明成员函数时必需 的,而定义成员函数则是可选的。在类内部定义的函数默认为inline。

2.const成员函数不能改变其所操作的对象的数据成员。const必须同时出现在声明和定义中,若只出现其中一处,就会出现一个编译时错误。

3.显示指定inline成员函数

在类内部定义的成员函数默认是inline。显示指定inline成员函数的办法有3种:

(1)类定义体内部指定inline,作为其声明的一部分。

(2)类定义体外部的函数定义上inline

(3)类定义体内和外均指定为inline

注意:inline成员函数的定义必须在调用该函数的每个源文件中时可见的。不在类定义体内定义的inline成员函数,其定义通常用放在有类定义的同一头文件中。

4.在一个给定的源文件中,一个类只能被定义一次。如果在多个文件中定义一个类,那么每个文件中的定义必须是完全相同的。

5.在声明之后、定义之前的类是一个不完全的类型。不完全类型只能以有限的方式使用。不能定义该类型的对象。不完全类型只能用于定义指向该类型的指针及引用,或者用于声明(而不是定义)使用该类型的作为形参类型或者返回类型的函数。

6.定义对象时,将为其分配存储空间,但(一般而言)定义类型时不进行存储分配。

7.在普通的非const成员函数中,this的类型是一个指向类类型的const指针,可以改变this所指向的值,但不能改变this所保存的地址。在const成员函数中,this的类型时一个指向const类类型对象的const指针。既不能改变this所指向的对象,也不能改变this所保存的地址。

8.不能从const成员函数返回指向类对象的普通引用。const成员函数只能返回*this作为一个const引用。

9.如果函数在类定义体之外定义,则用于返回类型的名字在类作用域之外。如果返回类型使用由类定义的类型,则必须使用完全限定名。

例如:

class Screen
{
public:
typedefstd::string::size_type index;
index get_cursor() const;
}; inline Screen::index Screen::get_cursor() const
{
return cursor;
}

该函数的返回类型时index,这是在Screen类内部定义的一个类型名。

10.当成员定义在类定义的外部时,要考虑在成员函数定义之前出现的全局作用域声明。

class Screen
{
public:
// ....
void setHeight(index);
private:
indexheight;
};
Screen::index verify(Screen::index); void Screen::setHeight(index var)
{
height =verify(var);
}

注意:全局函数verify的声明在Screen类定义之前是不可见的。然而名字查找可以考虑那些出现在成员函数定义之前的外围作用域声明,并找到全局函数verify的声明。

11.从概念上讲,可以认为构造函数分两个阶段执行:(1)初始化阶段;(2)普通的计算阶段。计算阶段由构造函数函数体中的语句组成。

不管成员是否在构造函数初始化列表中显示初始化,类类型的数据成员总是在初始化阶段初始化。初始化发生在计算阶段开始之前。

在构造函数初始化列表中没有显示提及的每个成员,使用与初始化变量相同的规则来进行初始化。运行该类型的默认构造函数,来初始化类类型的数据成员。内置或复合类型的成员的初始值依赖于对象的作用域:在局部作用域中这些成员不被初始化,而在全局作用域中他们被初始化为0。

例如:

Sales_item::Sales_item(const string &book)
{
isbn = book;
units_sold = 0;
revenue = 0.0;
}

这个构造函数给类Sales_item的成员赋值,但没有进行显示初始化。不管是否有显示的初始化式,在执行构造函数之前,要初始化isbn成员。这个构造函数隐式使用默认的string构造函数初始化isbn。执行构造函数的函数体时,isbn成员已经有值了。该值被构造函数函数体中的赋值所覆盖。

12.有些成员必须在构造函数初始化列表中进行初始化。对于这样的成员,在构造函数函数体中对它们赋值不起作用。

(1)没有构造函数的类类型的成员。

(2)const 成员。

(3)引用类型的成员。

13.只有当一个类没有定义构造函数时,编译器才会自动生成一个默认构造函数。

14.合成的默认构造函数使用与变量初始化相同的规则来初始化成员。具有类类型的成员通过运行各自的默认构造函数来进行初始化。内置和复合类型的成员,如指针和数组,只对定义在全局作用域中的对象才初始化。当对象定义在局部作用域中时,内置或复合类型的成员不进行初始化。

如果类包含内置或复合类型的成员,则该类不应该依赖于合成的默认构造函数。它应该定义自己的构造函数来初始化这些成员。

15.explicit关键字只能用于类内部的构造函数声明上。在类的定义体外部所做的定义上不再重复它。

通常,除非有明显的理由想要定义隐式转换,否则,单形参构造函数应该为explicit。将构造函数设置为explicit可以避免错误,并且当转换有用时,用户可以显示的构造对象。

16.友元机制允许一个类将对其非公有成员的访问权授予指定的函数或类。友元的声明以关键字friend开始。它只能出现在类定义的内部。

17.友元可以是普通的非成员函数,或前面定义的其他类的成员函数,或整个类。将一个类设为友元,友元类的所有成员函数都可以访问授予友元关系的那个类的非公有成员。当我们将成员函数声明为友元时,函数名必须用该函数所属的类名字加以限定。

注意:必须先定义包含成员函数的类,才能将成员函数设为友元。

18.非static数据成员存在于类类型的每个对象中。不像普通的数据成员,static数据成员独立于该类的任意对象而存在;每个static数据成员是与类关联的对象,并不与该类的对象关联。static成员函数没有this形参,它可以直接访问所属类的static成员,但不能直接使用非static成员。

19.可以通过作用域操作符从类直接调用static成员,或者通过对象、引用或指向该类类型对象的指针间接调用。

20.当我们在类的外部定义static成员时,无须重复指定static保留字,该保留字只出现在类定义体内部的声明处。

21.因为static成员不是任何对象的组成部分,所以static成员函数不能被声明为const,毕竟,将成员函数声明为const就是承诺不会修改该函数所属的对象。static成员函数也不能声明为虚函数。

22.static数据成员必须在类定义体的外部定义。不像普通数据成员,static成员不是通过类构造函数进行初始化,而是应该在定义时进行初始化。(保证对象正好定义一次的最好办法,就是将static数据成员的定义放在包含类的非内联成员函数定义的文件中。

定义static数据成员的方式与定义其他类成员和变量的方式相同:先指定类型名,接着是成员的完全限定名。

doubleAccount::interestRate = initRate();

注意,尽管initRate是私有的,我们仍然可以使用该函数来初始化interestRate。像任意的其他成员定义一样,interestRate的定义是在类的作用域中,因此可以访问该类的私有成员。

像使用任意的类成员一样,在类定义体外部引用类的static成员时,必须指定成员是在哪个类中定义的。然而,static关键字只能用于类定义体内部的声明中,定义不能标示为static。

23.特殊的整型const static 成员

一般而言,类的static成员,像普通数据成员一样,不能在类的定义体中初始化。相反,static数据成员通常在定义时才初始化。这个规则的一个例外是,只要初始化是一个常量表达式,整型const static数据成员就可以在类的定义体中进行初始化:

classAccount
{
public:
static double rate()
{
return interestRate;
}
static void rate(double);
private:
static const int period = 30;
double daily_tbl[period];
};

注意:const static 数据成员在类的定义体中初始化时,该数据成员仍必须在类的定义体之外进行定义。在类内部提供初始化式时,成员的定义不必再指定初始值:

const int Account::period;

24.static成员不是类对象的组成部分

static成员独立于任何对象而存在,不是类类型对象的组成部分。

(1)static 数据成员的类型可以是该成员所属的类类型。非static成员被限定声明为其自身类对象的指针或引用:

classBar
{
public:
//....
private:
static Bar mem1;
Bar* mem2;
Bar mem3;
};

(2)static数据成员可用作默认实参:

classScreen
{
public:
Screen& clear(char = bkground);
private:
static const char bkground = '#';
};

非static数据成员不能用作默认实参,因为它的值不能独立于所属的对象而使用。使用非static数据成员作默认实参,将无法提供对象以获取该成员的值,因而是错误的。

C++ Primer 有感(类)的更多相关文章

  1. C++ Primer 有感(管理类的指针成员)

    C++类的指针成员与其他成员有所不同,指针成员指向一个内存地址,该地址的内存需要我没管理. 我现在分析一下为什么要管理指针成员. 有如下Student类,Student.h如下: [cpp] view ...

  2. C++ Primer 有感(命名空间)

    1.命名空间定义以关键字namespace开始,后接命名空间的名字. 2.命名空间可以在全局作用域或其他作用域内部定义,但不能在函数或类内部定义. 3.定义在命名空间中的实体称为命名空间的成员.像任意 ...

  3. C++ Primer 与“类”有关的注意事项总结

    C++ 与"类"有关的注意事项总结(一) 1. 除了静态 static 数据成员外,数据成员不能在类体中被显式地初始化. 例如 : class First { int memi = ...

  4. C++ Primer 有感(异常处理)

    1.异常是通过抛出对象而引发的.该对象的类型决定应该激活哪个处理代码.被选中的处理代码是调用链中与该对象类型匹配且离抛出异常位置最近的那个. 2.执行throw的时候,不会执行跟在throw后面的语句 ...

  5. C++Primer学习——类

    我们在创建类的对象时,类不应该仅仅被声明,还应该被定义过,否则无法知道类占用了多少的内存 但是如果一个类的名字已经出现过就被认为是已经声明过了,所以允许包含自己的指针或者引用. 默认构造函数: 当类中 ...

  6. C++ Primer 有感(标准库vector及迭代器)

    vector是同一种对象的集合,每个对象都有一个对应的整数索引值.和string对象一样,标准库将负责管理与存储元素相关的类存.引入头文件 #include<vector> 1.vecto ...

  7. C++ Primer 有感(标准库map类型)

    map是键-值对的集合.map类型通常可以理解为关联数组:可以使用键作为下标获取一个值,正如内置数组一样.而关联的本质在于元素的值于某个特定的键相关联,而并非通过元素在数组中的位置获取. 1.map对 ...

  8. C++ Primer 有感(异常处理)(四)

    查看普通函数的声明的时候,不可能知道该函数会抛出什么异常,但是在捕获异常的时候要知道一个函数会抛出什么样的异常,以便捕获异常. 异常说明:指定,如果函数抛出异常,抛出的异常将是包含在该说明中的一种,或 ...

  9. C++ Primer 有感(异常处理)(三)

    先看下面的代码: [cpp] view plaincopy int main() { int *i=new int(10); /* 这中间的代码出现异常 */ delete i; return 0; ...

随机推荐

  1. 进程间通信——XSI IPC之消息队列

    进程间通信XSI IPC有3种:消息队列.共享内存.信号量.它们之间有很多相似之处,但也有各自的特殊的地方.消息队列作为其中比较简单的一种,它会有些什么东西呢,来一起探讨探讨.. 消息队列结构 消息队 ...

  2. Linux常见目录及命令介绍

    一.Linux中常用的目录介绍:     /        -根目录     /bin    -命令保存目录(普通用户亦可读取的命令)     /boot    -启动目录,启动相关文件     /d ...

  3. 2.docker常用命令

    一.安装相关 #查看docker是否安装 rpm -q docker #CentOS下安装docker   sudo yum install docker #启动 Docker systemctl s ...

  4. 百度地图JS 搜索悬浮窗功能

    这个需求的效果类似下面的截图,主要还是利用百度地图中自定义控件的功能,挺简单的.文档地址在这 http://lbsyun.baidu.com/index.php?title=jspopular 效果图 ...

  5. (译)Objective-C 类属性

    翻译自:Objective-C Class Properties 译者:Haley_Wong 由于Swift 3.0 出了太多令人兴奋的新特性,人们很容易忽略 Objective-C中的小改动.苹果展 ...

  6. cassandra 并发技术介绍

    摘要 本文主要介绍cassandra线程技术,cassandra的实现是基于java的,所以线程技术使用的也是jdk包提供的线程类.cassandra是分布式数据库,整个并发架构是基于阶段事件驱动架构 ...

  7. 360浏览器不能打开CSDN登陆页面

    碰见个奇葩问题: 使用360浏览器(广大程序员不要鄙视我~ 我有我的理由)不能打开csdn的登陆页面~~你登陆的时候,他就一直在那里打转~~ 但是用ie就可以打开登陆页面.... 怎么回事???难道C ...

  8. Linux telnet远程登录操作

    telnet  (如果不行 可以却换root帐户试试 su - root) 1.安装telnet-server     sudo dpkg -i xinetd_1%3a2.3.14-7ubuntu3_ ...

  9. 谷歌面试题:输入是两个整数数组,他们任意两个数的和又可以组成一个数组,求这个和中前k个数怎么做?

    谷歌面试题:输入是两个整数数组,他们任意两个数的和又可以组成一个数组,求这个和中前k个数怎么做? 分析: "假设两个整数数组为A和B,各有N个元素,任意两个数的和组成的数组C有N^2个元素. ...

  10. 1.Cocos2d-x-3.2编写3d打飞机,粒子管理器代码

     Cocos2d-x中的一个单例效果: #ifndef __Moon3d__ParticleManager__ #define __Moon3d__ParticleManager__ #inclu ...