C++类与对象

实现类成员函数

  • 定义成员函数时,使用作用域解析运算符(::)来表示函数所属的类。
  • 类方法可以方位类的 private 组件。
  • 同一个类的其他成员函数不必使用作用域解析运算符,就可以使用该类下的方法。

内联方法

  • 定义位于类声明中的函数都将自动成为内联函数。(定义是有函数体)
  • 也可在类声明外定义成员函数,只需在定义函数前加 inline 限定符。
  • 内联函数在编译时,会将此内联函数代码直接编译到调用函数之处。减少了一次函数调用时的跳转、数据压栈等操作。所以相比调用函数,内联函数的执行效率要相对高点。不过也正因为如此,所以最终生成的程序文件比较大。
  • 内联函数要求在每个使用它们的文件中都对其进行定义。

构造函数

  • 名称与类名相同,没有返回值,没有声明类型。
  • 默认构造函数:
    在未提供显式初始值时,用来创建对象的构造函数。
    当且仅当没有定义任何构造函数时,编译器才会提供默认构造函数。但如果为类定义了构造函数,同样必须提供默认构造函数。
  • 定义默认构造函数的两种方法:
    1.给已有构造函数的所有参数提供默认值
    2.没有任何参数

复制构造函数

用于将一个对象复制到新创建的对象中,即用于初始化过程,而不是常规的赋值过程,它接受一个指向类对象的常量引用作为参数:

Class_name(const Class_name &);

何时调用:

  • 新建一个对象并将其初始化为同类现有对象时,复制构造函数都将被调用;
    每当程序生成了对象副本时,编译器都会使用复制构造函数,即,当函数按值传递对象或函数返回对象时,都会使用复制构造函数;
  • 注意:由于按值传递对象会调用复制构造函数,因此应该按引用传递对象,这样可以节省调用构造函数的时间以及存储新对象的空间。

注意:

  • 如果类中包含了使用 new 初始化的指针成员,应当定义一个复制构造函数,以复制指向的数据,而不是指针,这被称为深度复制。
  • 如果需要使用复制构造函数但没有定义,编译器将自动生成一个

深度复制:
复制字符串并将副本的地址赋给 str 成员,而不仅仅复制字符串的地址,这样每个对象都有自己的字符串,而不是引用另一个对象的字符串。调用析构函数时都将释放不同的字符串,而不会去释放已经被释放的字符串,从而发生错误。

析构函数

  • 名称与类名相同,类名前加上 ~,没有返回值,没有声明类型,每个类只有一个。

  • 如果构造函数使用了 new ,则必须提供使用 delete 的析构函数。

  • delete(无论带不带中括号)都可以用于空指针

  • 对不是使用 new 初始化的指针使用 delete 时,结果将是不确定的。

  • 由编译器决定什么时候调用:
    如果创建的是静态存储类对象,则其析构函数将在程序结束时自动被调用;
    如果创建的是自动存储类对象,则析构函数在程序执行完代码块时(该对象是在其中定义的)自动被调用;
    如果对象是通过 new 创建的,则它将驻留在栈内存或自由存储区中,当使用 delete 来释放内存时,其析构函数将自动被调用。

this 指针

this 指针被设置为调用对象的地址,*this 是该对象的别名。

注意

Stock stock2 = Stock("Boffo Objects",2,2.0);
stock1 = Stock("Nifty Foods",10,20.0);

这两条语句有根本性差别:第一条语句是初始化,它可能会创建临时对象(也可能不会);第二条语句是赋值,总会在赋值前创建一个临时对象。初始化效率更高。

const 成员函数

只要类方法不修改调用对象,就应将其声明为 const ,如,函数定义为void Stock::show() const声明时void show() const;

static 类成员函数

  • 不能通过对象调用静态成员函数,静态成员函数不能使用 this 指针。
  • 如果静态成员函数实在公有部分声明的,则可以使用类名和作用域解析运算符来调用它。
  • 静态成员函数只能使用静态数据成员。

对象数组

初始化对象数组的方案是,首先使用默认构造函数创建数组元素,然后花括号中的构造函数将创建临时对象,然后将临时对象的内容复制到相应的元素中。因此,要创建类对象数组,这个类必须有默认构造函数。

作用域为类的常量

class Bakery
{
private:
	const int Months = 12;
	double costs[Months];
	...

这是行不通的!
可以使用下面两种方法:

  1. 在类中声明一个枚举。但声明的枚举不会创建类数据成员,即所有对象中都不包含枚举。
  2. 使用关键字 static 。

重载

运算符重载

  • 格式:operatorop()
  • op 是有效的C++运算符,如 operator+() 重载 + 运算符。
  • 重载后若运算符两侧是不同类型的对象,则左侧操作数是调用对象。

友元

友元函数

  • 类的友元函数是非成员函数,它的访问权限与成员函数相同。
  • 关键字friend,并将其原型放在类声明中,但友元函数不是成员函数,不能使用成员运算符(.)来调用。
  • 编写函数定义时,不要使用 Time:: 限定符,不要在定义中使用 friend 。

explicit

  • C++中, 一个参数的构造函数(或者除了第一个参数外其余参数都有默认值的多参构造函数), 承担了两个角色。 1 是个构造器 ,2 是个默认且隐含的类型转换操作符。

    所以, 有时候在我们写下如 AAA = XXX, 这样的代码, 且恰好XXX的类型正好是AAA单参 数构造器的参数类型(或者除了第一个参数外其余参数都有默认值的多参构造函数), 这时候编译器就自动调用这个构造器, 创建一个AAA的对象。

    这样看起来好象很酷, 很方便。 但在某些情况下, 却违背了我们(程序员)的本意。 这时候就要在这个构造器前面加上explicit修饰, 指定这个构造器只能被明确的调用/使用, 不能作为类型转换操作符被隐含的使用。

转换函数

从类类型转换到某种类型,是用户定义的强制类型转换。

operator typeName();

typename 为要转换的类型

  • 转换函数必须是类方法
  • 转换函数不能指定返回类型
  • 转换函数没有参数

静态类成员变量

  • 无论创建了多少个对象,程序只创建一个静态类变量副本,即类的所有对象共享同一个静态成员。
  • 不能在类声明中初始化静态成员变量,而应在类方法的文件中初始化。(这是因为类声明位于头文件中,程序可能将头文件包含在其他几个文件中,如果在头文件中进行初始化,将出现多个初始化语句副本,从而引发错误)
  • 如果静态成员是 const 整数类型或枚举型,则可以在类声明中初始化。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值