c++ primer复习(五):类
一:基本内容
1 类
数据成员:用于存储与类对象相关联的状态
成员函数:对数据成员进行操作
类将接口与实现分离,接口指定了类支持的操作,操作的具体实现细节是类的设计者才需要了解
2 类成员
类成员可以是数据(数据成员)、函数(成员函数)、类型别名
数据成员:类不能具有自身类型的数据成员,但是可以使指向自身类型的指针或引用
成员函数:在类内部定义的成员函数默认为内联inline函数,成员函数的内联可以在声明处也可以在定义处指出
const成员函数不能改变其所操作的对象的数据成员,const成员函数的const必须同时出现在声明和定义中
3 数据抽象和封装
数据抽象依赖于接口与实现相分离的编程技术,使用者只需抽象的考虑对象执行的类操作,无需关心如何实现
类是一个封装实体,类类型隐藏了类的多数成员
访问标号来定义类的抽象接口和实施封装
4 数据成员重载
struct A
{
int a;
}; struct B : A
{
int a;
}; struct B x;
cout << &x << endl;
cout <<&x.a << endl; struct A *pa = &x;
struct B *pb = &x;
cout << &(pa->a) << endl;
cout << &(pb->a) << endl;
结果:
0x7fffc2c00b40 x对象的起始地址
0x7fffc2c00b44 x对象中x.a的地址,可见前面有一个A::a
0x7fffc2c00b40 说明静态绑定,pa的静态类型是A,所以pa->a是A::a
0x7fffc2c00b44 说明静态绑定,pb的静态类型是B,所以pb->a是B::a
普通的数据成员重载,会在派生类中形成两个同名的成员(其实没有重载,而是正常继承了基类的成员,同时正常产生自己的成员,只不过两个成员的名字相同而已)
5 成员函数重载
通过在派生类中重新定义基类函数,派生类可以覆盖、替换掉基类的函数定义
这种覆盖是动态还是静态,取决于成员函数是否被声明为虚函数
class A
{
public:
int a;
virtual void func(){cout << "a ";cout << a << endl;}
}; class B : public A
{
public:
int a;
void func()
{
cout << a << endl;
A::func();
}
}; int main()
{
B b;
b.a = ;
b.A::a = ;
b.func();
b.A::func();
}
执行结果:
2
a 3
a 3
子类中的数据成员无论是否与父类中的数据成员同名,父类的数据都会被正常继承
如果子类重载了父类的成员函数,则会发生覆盖,但是仍然可以通过 父类名::成员函数名 的方式在子类中调用父类成员函数,同时由于数据成员会正常继承下来,所以用子类对象调用父类成员函数时,子类对象中的数据包含了父类的数据成员,成员函数中访问的变量会使用子类中继承下来的变量,无论变量名是否与子类中的相同
除了虚函数,其他函数和数据都是静态绑定!!
b.A::func()中的func函数含有一个隐含的this指针 A *const,所以this->a将发生静态绑定,将调用实例b中的基类部分的数据a
基于const的重载:可以理解为const成员函数的隐藏this指针类型为 const A *const,非const成员函数的隐藏this指针类型为A *const,形参不同,实现函数重载
6 可变数据成员
即使在const成员函数中,仍然可以被改变的数据成员,需要被声明为mutable成员
二:构造函数
1 初始化列表
构造函数的初始化列表以冒号开始,就算没有显示执行初始化列表,在构造函数函数体执行之前,还是会以默认的方式初始化成员(按照变量声明的顺序)
所以初始化列表可以理解为并不是执行初始化,而是为数据成员初始化提供了一种选择。所以没有默认构造函数的成员一定要在初始化列表中
默认初始化中,内置类型的成员的初始值取决于类对象的作用域,局部作用域中不被初始化,全局作用域中被初始化为0
成员初始化的顺序按照定义的顺序,而不是按照初始化列表中的顺序,这点可能造成程序出错:
class X{
int i;
int j;
public:
X(int val):j(val),i(j){}
};
先初始化i,但初始化列表中i依赖于j,所以i最终初始化的值可能并非我们想要的值(这里如果X对象实例是局部变量,i的值将随机,X若是全局变量,i的值为0)
初始化列表中,可以向数据成员传递满足数据成员类型的构造函数的各种形式的形参
2 默认构造函数
一个类如果定义了自己的构造函数,编译器将不会合成默认的构造函数
需要注意的是,如果一个类A的数据成员中有另一个没有默认构造函数的类B,那么编译器不会为A合成默认构造函数
具有默认构造函数的类A的对象,不能用 A a()进行定义,而是 A a
3 每个构造函数都定义了一个隐式转换
explicit声明的构造函数,可以抑制由构造函数定义的隐式转换,explicit只用于类构造函数的声明中,类外部定义的构造函数,不需要也不能加上explicit限定
三 其他
1 友元函数
友元机制允许一个类将 对其非公有成员的访问权 授予指定的函数或类
友元声明只能出现在类定义的内部,通常将友元成组的放在类定义的开始或结尾是个好主意
2 static数据成员
对特定类类型的全体对象而言,有时候需要访问一个全局对象,但是全局对象会破坏封装(一般的用户代码就可以修改这个全局对象),类的static数据成员独立于该类的任意对象而存在,该数据成员与类相关联,而不是与对象相关联
static数据成员必须在全局范围内进行初始化 使用 type classname::x的形式,此时不能指定static限定
static const成员和const static成员,只有int类型可以在类内部初始化,其他任何类型都要在外部全局范围内进行初始化,不能在初始化列表上
static const int既可以在类内部初始化,又可以在外部全局进行初始化,但只能初始化一次
static成员既可以用A::来调用,又可以用a.来调用
无论是public还是private,static数据正常遵循上面的初始化规则,同时正常遵循public、private的权限设定
3 static成员函数
static成员函数没有this指针,可以直接访问所属类的static成员,但是不能访问类的非static成员
static成员函数不能被声明为const(const函数说明函数不修改调用对象的数据,static成员本身就不会访问对象的数据)
static成员函数不能被声明为虚函数
c++ primer复习(五):类的更多相关文章
- C++ 11 从C++ primer第五版的学习笔记
1. auto (page107) auto 推断会忽略const const int ci = i, & cr = ci; auto b = ci; // b is an int (to ...
- javascript函数一共可分为五类: ·常规函数 ·数组函数 ·日期函数 ·数学函数 ·字符串函数
javascript函数一共可分为五类: ·常规函数 ·数组函数 ·日期函数 ·数学函数 ·字符串函数 1.常规函数 javascript常规函数包括以下9个 ...
- 实验楼课程管理程序-深入学习《C++ Primer第五版》实验报告&学习笔记1
本片博客为实验楼的训练营课程深入学习<C++ Primer第五版>的实验报告和学习笔记. 原课程地址为:https://www.shiyanlou.com/courses/405# 原文出 ...
- IP分为五类
IP地址分为五类: IP地址分为五类:A类保留给政府机构,B类分配给中等规模的公司,C类分配给任何需要的人,D类用于组播,E类用于实验. 常用的三类IP地址 IP = 网路地址(网络号)+主机地址(主 ...
- 最常用的五类CSS选择器
一些新手朋友对选择器一知半解,不知道在什么情况下运用什么样的选择器,这是一个比较头疼的问题,针对新手朋友,对CSS选择器作一些简单的说明,希望能对大家的学习工作有一定的帮助,更多的CSS知识请参考We ...
- IP分类:A,B,C,D,E五类
IP地址分为五类: IP地址分为五类:A类保留给政府机构,B类分配给中等规模的公司,C类分配给任何需要的人,D类用于组播,E类用于实验. 常用的三类IP地址 IP = 网路地址(网络号)+主机地址(主 ...
- C++PRIMER第五版练习题答案第一章
C++PRIMER第五版练习题答案第一章 应该有很多小伙伴和我一样,闲来无事买了本C++的书自己啃,课后的练习题做的很揪心,这里我分享下我写的答案,希望能帮助到你,提供源码,就不跑了哈,毕竟现在是第一 ...
- C++Primer第五版学习笔记
<C++ Primer>Learning Note 程序实例下载地址:http://www.informit.com/title/0321714113 第一章 开始 ...
- C Primer Plus--C存储类、链接和内存管理之存储类(storage class)
目录 存储类 作用域 链接 存储时期 自动变量 寄存器变量 具有代码块作用域的静态变量 具有外部链接的静态变量 extern关键字 具有内部链接的静态变量 多文件 存储类 C为变量提供了5种不同的存储 ...
随机推荐
- Detect combined string
写一个程序判断字符串A是否为其他两个字符串的组合,组合过程中其他两个字符串的相对顺序不能被破坏. 举例说明:abc和def可以组成字符串adebcf,但不能组成aefbcd,因为def的相对顺序已经被 ...
- 源码生成deb包
方法一 源码包要求是使用 automake 进行编译管理的. 安装路径不能指定为 /usr/local 下的目录,否则生成 deb 包期间报错. 制作的工具是 dh-make ,如果没有安装,要先安装 ...
- nyoj 325 zb的生日
01背包 zb的生日 时间限制:3000 ms | 内存限制:65535 KB 难度:2 描述 今天是阴历七月初五,acm队员zb的生日.zb正在和C小加.never在武汉集训.他想给这两位兄 ...
- hdoj 1702 ACboy needs your help again!【数组模拟+STL实现】
ACboy needs your help again! Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K ( ...
- Node.js学习(14)----EJS模板引擎
这个入门教程将从以下几个方面来讲解: 1. 引入EJS 2. 创建一个模板 3. 使用视图工具组件 4. 使用错误处理组件 5. 什么情况下应使用EJS 引入EJS 在我们正式开始前,我们先来做点准备 ...
- tensorflow 实现线性方程
下面的直接是代码: #!usr/bin/env python#coding:utf-8"""这个代码的作用是 通过 tensorflow 来计算 y = 0.3x + 0 ...
- sudo apt-get install gksu
exmyth@Inspiron-5437:/etc/default$ gksu gedit apport 程序“gksu”尚未安装. 您可以使用以下命令安装:sudo apt-get install ...
- 使用startCoroutine制定倒计时
使用startCoroutine制定倒计时 using UnityEngine; using System.Collections; public class TimerCoroutine : Mon ...
- oracle学习----DDL锁理解
DDL锁分为三种 1.排他DDL锁 2.共享DDL锁 3.可中断解析锁 大部分DDL都带有排他DDL锁,如一个表被修改中,可以使用select查询数据,但是大多数操作都是不允许执行的,包括所有其他DD ...
- 开源安全测试 - BackTrack的应用
开源安全测试 - BackTrack的应用: http://gdtesting.com/product.php?id=99