定义一个类:

class Myclass{
int data_i;
string data_str;
public: int getdata_i() const { return data_i; }
string getdata_str() const {return data_str; }
}; // 不要忘了分号!

我们用关键字class定义了一个C++类,我们也可以用struct来定义,两者的区别在于:用struct定义的类,在第一个访问控制说明符之前的类成员默认为public的,而class定义的类默认为private的。

因此,data_i和data_str就是private的。getdata_i()和getdata_str()分别获得两个成员的值,因为private的值可以由成员函数来访问,在成员函数中,隐式的传进去了一个参数this指针,这个指针的地址是类的地址。this指针类型为:Myclass *const ,所以,我们也可以显示的写出来:

int    getdata_i() const { return this->data_i; }

理论上,这两个函数并不会改变成员的值,因此我们可以将这两个函数定义为常量成员函数。 即就是在成员函数参数列表和函数体之间添加const关键字。

const用来修饰this的类型,添加了const会将this指针转变为具有底层cosnt的性质:const Myclass* const this。指向常量的指针不会修改对象的值,因此我们就是实现了不改变类成员的值的效果。常量对象,以及常量的引用和指针都只能调用常量成员函数

定义在类内部的成员函数默认为inline内联的,我们也可以指定定义在类外部的成员函数为内联函数:

我们为这个类新添加一个成员函数,并将其定义为inline的:

// 声明
inline void showdata() const;
// 定义
inline void Myclass::showdata() const
{
cout << data_i << ' ' << data_str;
}

类的构造函数:

我们没有为这个类定义任何的构造函数,那么编译器负责会为我们定义一个默认构造函数,也叫合成的默认构造函数。

并不是所有的类都能依赖合成的默认构造函数,原因有三:

1. 我们在类中定义了其他的构造函数,因为编译器只有在我们没有定义任何构造函数时才会为我们定义一个默认构造函数。除非我们再定义一个默认的构造函数,否则我们没有默认构造函数。

2. 如果我们的类中有内置类型成员或复合成员类型,只有这些成员都被赋予了类内初始值时,这个类才适合使用合成的默认构造函数。

3. 如果类中包含另一个类类型的成员,而且这个类没有默认构造函数,那么编译器无法初始化这个成员。

在C++11中,我们可以使用 =default 来要求编译器生成默认构造函数。

在构造函数初始值列表中,初始化顺序和它们出现的顺序一致。

如果一个构造函数为所有的参数都提供了默认实参,实际上它就是个默认构造函数。

友元:一般来说,最好在类定义开始的地方或结束前的位置集中声明友元。我们可以将一个类声明为另一个类的友元,那么这个友元类的成员就可以访问它的所有成员了。

也可以将一个函数定义为一个类的友元,只需在开头加一个friend就可以:

class Myclass1
{ int i;
public:
int geti()const{return i;}
void show(Myclass&);
};
<pre name="code" class="cpp">friend class Myclass1; // 友元类
friend void showData(); // 友元函数

我们还可以将一个类的成员函数声明为另一个类的友元:

friend void Myclass1::show(Myclass&);

我们需要按照如下方式设计:

1. 先定义Myclass类,声明show函数,不能定义它,在show函数使用Myclass之前必须先声明Myclass。

2. 接下来定义Myclass,包括对show友元函数的声明。

3. 最后定义show,此时它才可以使用Myclass的成员。

尽管重载函数的名字一样,但仍然是不同的函数,我们要在类中声明一组重载函数为友元时,需要逐个声明。

类的特性:

在常量成员函数中,理论上我们是不可以修改成员的值,但是我们可以添加关键字mutable来实现可以更改成员的值,我们可以追踪一个常量成员函数被调用了多少次:

mutable size_t  find; // 为Myclass添加一个成员
void mutabledata()const{ ++find;} //添加函数

mutabledata函数是个常量成员函数,理论上不可以更改成员的值,但我们将find声明为mutable,我们就可以更改了。

我们还可以为类成员提供默认初始值,当我们提供一个初始值时,必须以符号= 或者花括号表示。

从const成员函数以引用的形式返回*this时,它的返回类型将是常量引用。

类的静态成员:

我们可以为Myclass类声明一个静态成员和静态成员函数:

static int data_static;

static void showsta();

类的静态成员存在于任何类对象之外,它不与任何对象绑在一起,也不包含this指针。静态成员函数不能声明为const的,在静态成员函数内也不能使用this指针。

我们使用作用域运算符直接访问类的静态成员 函数:

int x;
x = Myclass::showsta();

虽然静态成员不属于类的某个对象,但我们仍然可以使用类对象、引用或指针来访问静态成员。

静态成员可以在内部定义,也可以在外部定义,在外部定义时,不能重复static关键字。

void Myclass::showsta()
{
cout << data_static;
}

通常情况下,类的静态成员不应该在类内初始化,如果我们将其声明为常量成员,则可以在内部定义。其初始值必须为常量表达式。

static constexpr double data_db = 1;

即使一个常量静态成员在类内定义,通常情况下,我们也应该在类的外部定义下该成员,但是不能带初始值:

constexpr double Myclass::data_db;

因为静态成员独立于任何对象,所以静态数据成员可以是不完整类型,特别的,静态数据成员的类型可以就是它所属的类类型,而非静态成员则受到限制,只能声明为它所属类的指针或引用,静态成员还可以作为默认实参。

C++ Primer:第七章:类的更多相关文章

  1. <<C++ Primer>> 第 7 章 类

    术语表 第 7 章 类 抽象数据类型(abstract data type): 封装(隐藏)了实现细节的数据结构.    访问说明符(access specifier): 包括关键字 public 和 ...

  2. C#图解教程 第七章 类和继承

    类和继承 类继承访问继承的成员所有类都派生自object类屏蔽基类的成员基类访问使用基类的引用 虚方法和覆写方法覆写标记为override的方法覆盖其他成员类型 构造函数的执行 构造函数初始化语句类访 ...

  3. C++Primer 第七章

    //1.定义在类内部的函数是隐式内联的. //2.默认情况下,this指针的类型是指向类类型非常量版本的常量指针.对于类的常量成员函数的声明方法是:将const放置于成员函数的参数列表后,用于修饰th ...

  4. [C++ Primer] 第7章: 类

    定义抽象数据类型 定义在类内部的函数是隐式的inline函数. const成员函数 又叫做常量成员函数, 成员函数参数列表之后紧跟const关键字, const修饰的是类this指针. 默认情况下th ...

  5. 第七章 类(class)7.1 笔记

    最好不要把对象的定义和类的定义放在一起,这么做无异于把两种不同实体的定义混在了一条语句里,一会定义类,一会又定义变量,显然这是一种不被建议的行为. 类的定义最后要加上分号(:) 成员函数的声明必须放在 ...

  6. 【C++】《C++ Primer 》第七章

    第七章 类 一.定义抽象数据类型 类背后的基本思想:数据抽象(data abstraction)和封装(encapsulation). 数据抽象是一种依赖于接口(interface)和实现(imple ...

  7. ArcGIS API for JavaScript 4.2学习笔记[24] 【IdentifyTask类】的使用(结合IdentifyParameters类)(第七章完结)

    好吧,我都要吐了. 接连三个例子都是类似的套路,使用某个查询参数类的实例,结合对应的Task类,对返回值进行取值.显示. 这个例子是Identify识别,使用了TileLayer这种图层,数据来自Se ...

  8. [Java编程思想] 第七章 复用类

    第七章 复用类 第一种方法非常直观:只需在新的类中产生现有类的对象(组合). 第二种方法更细致一些:它按照现有类的类型来创建新类(继承). 7.1 组合语法   只需将对象引用置于新类中即可. cla ...

  9. C primer plus 读书笔记第六章和第七章

    这两章的标题是C控制语句:循环以及C控制语句:分支和跳转.之所以一起讲,是因为这两章内容都是讲控制语句. 第六章的第一段示例代码 /* summing.c --对用户输入的整数求和 */ #inclu ...

  10. C++ Primer Plus学习:第七章

    C++入门第七章:函数-C++的编程模块 函数的基本知识 要使用C++函数,必须完成如下工作: 提供函数定义 提供函数原型 调用函数 库函数是已经定义和编译好的函数,可使用标准库头文件提供原型. 定义 ...

随机推荐

  1. C++-指针和引用的区别

    1,不存在空引用,指针可以为空 2,引用更高效,使用前不需要测试是否为空 3,指针可以被赋给别的对象,引用则不可以更改 总之,在对象有可能什么也不指向或者指向不同的对象的时候应该使用指针.

  2. [vijos P1014] 旅行商简化版

    昨天早上上课讲旅行商问题,有点难,这周抽空把3^n的算法码码看.不过这个简化版已经够折腾人了. 其一不看解析不知道这是双进程动态规划,不过我看的解析停留在f[i,j]表示第一个人走到i.第二个人走到j ...

  3. Setup Factory 打包.netframework 2.0

    在setup factory 的安装目录下的Dependencies中新建目录dotnet20/并放入dotnetfx2.0.exe: Dependencies目录中再加xml文件dotnet20.x ...

  4. C++ primer的第一章的主要内容

    第一章主要是把C++的主要的部分简单的介绍了一下,让读者对C++开始有一个简单的了解.看完第一章的收获就是知道如何去读入不确定数目的输入,主要是形式是:whlie(cin>>s){},利用 ...

  5. ACM - 动态规划专题 题目整理

    CodeForces 429B  Working out 预处理出从四个顶点到某个位置的最大权值,再枚举相遇点,相遇的时候只有两种情况,取最优解即可. #include<iostream> ...

  6. matlab求曲线长度

    曲线段在上的弧长为采用积分所求弧长s=∫√(1+y'²)dxmatlab求出各点的导数,然后按照上式积分 clear>> x=1:0.1:10;>> y=rand(1,leng ...

  7. 如何通过 GT 快速开始性能测试?

    http://gt.tencent.com/docs/a/2.1/GTAndroidQuickStart.pdf Summary 安装 GT(GT.apk)后,不需要连接 PC 和在被测应用中插入代码 ...

  8. Interview----用最快的方法计算 Fibonacci 数

    输入 n, 用最快的方法求该 Fibocacci 数列的第 n 项. 方法1: 递归,非常慢 方法2: 迭代,因此计算 f[1] , f[2], f[3] ,,,, 复杂度 O(N) 方法3: 采用以 ...

  9. 开源软件项目管理系统招设计/开发。。。。。Zend Framework2架构 svn://735.ikwb.com/pms

    开源软件项目管理系统招设计/开发.....Zend Framework2架构svn://735.ikwb.com/pms

  10. ecpilise引入Maven项目目录不正常,无JRE,无Maven Dependencies

    原因是我的eclipse默认open perspective是java ee,改成java就恢复正常了.