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. centos 7.X & centos6.X 防火墙基本命令

    Centos 7 firewall 命令:查看已经开放的端口: firewall-cmd --list-ports 开启端口 firewall-cmd --zone=public --add-port ...

  2. Git-gitblit-Tortoisegit 搭建Windows Git本地服务器

    1.Gitblit安装 1.1.Gitblit简介 Git在版本控制领域可谓是深受程序员喜爱.对于开源的项目,可以免费托管到GitHub上面,相当的方便.但是私有项目托管到GitHub会收取相当昂贵的 ...

  3. ACM Smallest Difference

    给定一些不同的十进制数字(distinct decimal digits),您可以通过选择这些数字的非空子集(non-empty subset)并以某种顺序编写它们,从而形成一个整数. 剩下的数字可以 ...

  4. Docker配置 DNS

    Docker 没有为每个容器专门定制镜像,那么怎么自定义配置容器的主机名和 DNS 配置呢? 秘诀就是它利用虚拟文件来挂载到来容器的 3 个相关配置文件. 在容器中使用 mount 命令可以看到挂载信 ...

  5. 简单将sublime text 配置为lua或c#一键编译运行环境

    lua { "cmd": "luajit $file", "selector":"source.lua" } C { & ...

  6. 安卓高级4 第三方库SlidingMenu的使用

    源码位于github上(本人fork地址):点击进入地址 效果图: 使用方法:下载源码后 解压其中的文件夹library 到任意地方 修改library中gragle 其方法参考另一个博客(建议先修改 ...

  7. Spark技术内幕:Sort Based Shuffle实现解析

    在Spark 1.2.0中,Spark Core的一个重要的升级就是将默认的Hash Based Shuffle换成了Sort Based Shuffle,即spark.shuffle.manager ...

  8. 大数据基础知识问答----hadoop篇

    handoop相关知识点 1.Hadoop是什么? Hadoop是一个由Apache基金会所开发的分布式系统基础架构.用户可以在不了解分布式底层细节的情况下,开发分布式程序.充分利用集群的威力进行高速 ...

  9. Redis 学习笔记4: Redis 3.2.1 集群搭建

    在CenOS 6.7 linux环境下搭建Redis 集群环境 1.下载最新的Redis版本 本人下载的Redis版本是3.2.1版本,下载之后,解压,编译(make): 具体操作可以参考我的博文:R ...

  10. java.util.Arrays类详解(源码总结)

    概述 Arrays类位于java.util包下,是一个对数组操作的工具类.今天详细的看了看Arrays类的4千多行源码,现将Arrays类中的方法做一个总结(JDK版本:1.6.0_34).Array ...