定义一个类:

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. 内工大acm校赛--整理代码

    题目:小明搜到一行无缩进无换行代码,请帮小明整理代码.无for语句和case语句,而且只有一个主函数.你只要控制注意“:”“{”“}”这三个符号带来的缩进和换行效果就行. Input: 输入只有一行, ...

  2. android 回调函数

    http://blog.csdn.net/xiaanming/article/details/8703708 此为回调的java 实例 http://www.cnblogs.com/qingchen1 ...

  3. Vm下 linux与windowsxp文件共享的方法

    我的PC Operating System Host是Windows XP,Guest是Linux,virtualPC是VMware workstation.方法介绍大全请参见:Windows与Vmw ...

  4. iphone/ipod网页开发教程及规则

    侦测iPhone/iPod 开发特定设备的移动网站,首先要做的就是设备侦测了.下面是使用Javascript侦测iPhone/iPod的UA,然后转向到专属的URL. if((navigator.us ...

  5. 扩展jQuery easyui datagrid增加动态改变列编辑的类型

    $.extend($.fn.datagrid.methods, { addEditor : function(jq, param) { if (param instanceof Array) { $. ...

  6. 爬虫学习--使用百度api---天气

    #coding:utf-8#version:0.1#note:该即用API能查询指定城市的空气质量指数,但城市数量有限,截止2015年3月26日,只能查到全国161个城市的. import urlli ...

  7. BZOJ 4027 兔子与樱花

    原来想的是给所有点排序....但是要修改啊...然后发现对于儿子排序就可以了. #include<iostream> #include<cstdio> #include< ...

  8. ERP仓库管理系统(九)

    需求分析: 1.设计库房表,至少包括两个字段,库房名称,库房所属公司的ID(在客户资质审批表中找到对应公司的ID) 2.设计增.删.改.查一套程序,其中的删除要做限制,只要有库存数据存在则不允许删除对 ...

  9. 谷歌、火狐浏览器gift图片缓存后不显示动态效果

    <script> $(function(){ $('.center img').prop("src","images/service/01.gif" ...

  10. 【转】关于iPhone界面适配详细版本

    对于上面哪一张适配图很多人不了解什么意思,现在我就慢慢地解释一下. 下面我们观看一下我们需要的几张效果图 3GS手机 iPhone 4/4S iPhone 5/5c/5s iPhone 6 iPhon ...