C++ Primer 学习笔记十二 —— 类

记录笔记原则:

1.用简单易懂的语言叙述自己的理解,避免照搬原文

2.用实例说明,避免空洞

3.多做总结和横向对比,避免片面


类定义

类就是定义了一个新的类型和一个新的作用域;

数据成员存储对象的状态,函数成员改变对象的状态;


数据抽象和封装

类的基本思想是数据抽象和封装;

封装是屏蔽细节,抽象是提取共性;

把狗的共性提取出来形成class Dog是抽象的过程,把狗的属性和行为的细节隐藏起来是封装;

举例说明:vector是抽象和封装的,数组既不抽象也不封装,pair类不是抽象的且封装的不良好;


类成员

数据成员;函数成员;类型别名(typedef)


class VS struct

struct成员默认是公有的,class默认是私有的


inline成员函数

类内部定义的函数自动为inline;

在声明和定义处指定都可以;

inline成员函数可在类体内或体外定义,单必须在头文件中定义,因为在编译阶段自动扩展;


宏 VS inline

宏在预编译阶段扩展,无类型检测;inline在编译阶段扩展,类型检测;


const成员函数

const必须同时出现在声明和定义中;

const对象只能使用const成员函数,普通对象可以使用任意成员,例外是构造函数,构造函数不能为const;


this指针

每个成员函数都有一个附加的隐含形参,this;

普通成员函数,this的类型是指向类类型的const指针,例如 A *const this;

const成员函数,this的类型是指向const类类型的const指针,例如const A *const this,因此我们无法在const成员函数中修改对象;

如果一定要在const成员函数中修改数据成员,可声明为mutable;


类作用域

形参表和函数体在类作用域中,返回类型不在;

// 返回类型出现在成员名字前面,不在类作用域中,所以添加完全限定名
Screen::index Screen::get(index r)
{    
    index row = r * 10;    
    return row;
}


类作用域中的名字查找

void Screen:dummy(index height)
{
    index a = height * 10;  // 函数参数
    index b = this->height * 10;  // 对象成员
    index d = Screen::height * 10;  // 对象成员
    index d = ::height * 10;  // 全局变量
}


构造函数

构造函数分两个阶段执行:1、初始化阶段(不管是否有初始化列表都要进行初始化);2、普通的构造函数体语句执行;

在初始化阶段,类使用默认构造函数初始化,内置或复合类型的成员的初始值依赖于对象的作用域:如果对象在全局作用域中将初始化为0,否则不被初始化;

注意:如果类成员没有提供初始化列表,并且那个类没有默认构造函数,则编译失败;

初始化const和引用数据成员的唯一机会是在初始化列表中;

成员初始化的顺序是定义成员的次序,而不是初始化列表中的次序;


默认构造函数

只要定义了一个构造函数(默认的、或者有参数的),编译器将不会自动生成默认构造函数;

好的习惯是,给每个类显示定义一个默认构造函数;

class A
{
    public:
        A(int a);
}
A obj;   // 错误
A *p = new A[10];  // 错误

使用默认构造函数不能再后面加空括号

A myobj();  // 函数声明
A myobj;  // 定义对象,调用默认构造函数
A myobj = A();  // 无名的临时对象


隐式转换

单个形参的构造函数定义了一个隐式转换;

class A
{
    public:
        A(string str);
        bool equals(A obj);
}
 
A obj = "hello C++";  // 隐式转换为A对象
bool result = obj.equals("hello C++");  // 隐式转换为A对象

抑制隐式转换的方法:将构造函数声明为explicit

好的习惯是将单形参构造函数应该都声明为explicit,避免隐式转换

class A
{
    public:
        explicit A(string str);
        bool equals(A obj);
}
 
A obj = "hello C++";  // 错误
bool result = obj.equals("hello C++");  // 错误


友元

友元不是类的成员,因此不受访问控制的限制


static类成员

static独立于对象存在,换种说法是所有对象共有;

static成员 VS 全局变量

全局变量破坏封装性,static成员名字在作用域中避免重名冲突,并且可以为私有成员,实现封装;

static函数没有this指针,所以无法调用普通成员,只能使用static成员;

static成员不能在构造函数中初始化,只能在类外初始化,特例是const static成员可以在类的定义体中初始化;


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值