C++ —— 成员函数复习

this 和 const

所有的成员函数其实都包含一个隐式参数 *this。由于不会显式传递调用函数的对象,因此不能在参数前面加上 const 表示成员函数不会修改调用该函数的对象,而是在函数后面加上 const 关键字。

void Class::show() const;
// =>
void show(const Class &);

成员函数

声明成员函数

类成员函数的声明和普通函数的声明类似。

class Demo {
private:
    int value;
    double num;
public:
    int showFunc(int);
}

实现成员函数

类成员函数的实现和普通函数的实现有一些区别。类成员函数实现时函数名需要使用全名(限定名),成员函数可以访问类的私有成员。

int Demo::showFunc(int) {
	// 实现细节
}

内联成员函数

  1. 隐式内联。直接在类声明中用成员函数定义替换成员函数声明,则该函数会成为内联函数。
class Demo {
private:
    int value;
    double num;
public:
    int showFunc(int v) { 实现细节; }
}
  1. 显式内联。在成员函数的定义处使用 inline 可以显式地将成员函数声明为内联函数。
class Demo {
private:
    int value;
    double num;
public:
    int showFunc(int);
}

inline int Demo::showFunc(int v) {
    // 实现细节
}

构造函数

什么是构造函数

构造函数在创建对象时被自动调用。
特点:构造函数的函数名与类同名;没有返回类型;可以声明特征值不同的构造函数(重载)。
注意:当程序员没有声明构造函数,编译器会生成一个默认构造函数;一旦程序员声明了构造函数,编译器就不会再生成默认构造函数。

class Demo {
private:
    int value;
    double num;
public:
	Demo();
    Demo(int, double);
}    

默认构造函数

Q:什么是默认构造函数?
A:不接受任何参数的构造函数。

class Demo {
private:
    int value;
    double num;
public:
	Demo();
} 
// 隐式调用
Demo d1;
// 显式调用
Demo d2();
Demo d3 = Demo();

复制构造函数

Q:什么是复制构造函数?
A:只接受一个参数的构造函数,并且该参数的类型和类一样。

class Demo {
private:
    int value;
    double num;
public:
	Demo(const Demo &);
}    
// 隐式调用
Demo d1 = d;
// 显式调用
Demo d2 = Demo(d);

容易混淆:复制构造函数和重载赋值运算符的使用时机。

当程序员没有声明复制构造函数,编译器会生成一个默认复制构造函数;一旦程序员声明了复制构造函数,编译器就不会再生成默认赋值构造函数。默认的复制构造函数的实际效果就是逐成员复制(浅拷贝)。对于成员函数需要使用动态内存分配的情况时,需要定义复制构造函数(深拷贝)。

转换构造函数

Q:什么是转换构造函数?
A:只接受一个参数的构造函数,并且该参数的类型是其他类型。该构造函数可以将其他类型的变量转换为类类型。

class Demo {
private:
    int value;
    double num;
public:
	Demo(Type t);
}    
Type tmp;
// 隐式调用
Demo d1 = tmp;
Demo d2;
d2 = tmp;

// 显式调用
Demo d3 = Demo(tmp);

其中 Type 为除了 Demo 之外的类型,可以是基本数据类型,也可以是程序员自定义的类型。

定义了转换构造函数之后就可以让其他类型变量自动转换为类类型,但是有时候这种特性并不招人喜欢,使用 explicit 关键字可以关闭隐式转换。

析构函数

析构函数在对象被销毁时被编译器自动调用。
特点:函数名为类名前面加上~;没有返回类型;没有参数。
注意:构造函数可以有参数,因此可以被重载,但是析构函数不接受参数,因此一个类只能有一个析构函数;通常,不需要我们编写析构函数,但是当类成员涉及动态内存分配时,需要编写析构函数。

class Demo {
private:
    int value;
    double num;
public:
	~Demo();
}    

运算符重载

运算符重载格式:

returnType operator[op](argList);

运算符重载的参数必须至少有一个是自定义类型;不能更改运算符的操作对象数目;运算符重载可以是成员函数,也可以是非成员函数,不过非成员函数通常被设为友元函数;. .* :: ?: sizeof 这5个运算符不能被重载。

class Demo {
private:
    int value;
    double num;
public:
    // 成员函数的重载运算符
	Demo & operator*(double);
    // 友元函数的重载运算符
    friend std::ostream & operator<<(std::ostream &, const Demo &); 
}
// 普通非成员函数的重载运算符, 不能直接访问类的私有成员
Demo & operator+(const Demo & d1, const Demo & d2); 

/*
 * 函数实现
 */
Demo & Demo::operator*(double d) {
	// 实现细节
}
std::ostream & operator<<(std::ostream & out, const Demo & d) {
    
}
Demo & operator+(const Demo & d1, const Demo & d2) {
	// 实现细节
}

注意:友元函数的关键字 friend 只能出现在类内,即只能在函数声明时使用,在函数定义处不能出现 friend (explicit 关键字也一样),详见 operator<< 的函数定义和函数实现。

转换函数

转换构造函数可以将其他类型对象转换为类类型;而转换函数则是反过来将类类型转换为其他类型。
特点:转换函数没有返回类型,因为返回的类型已经由 typeName 表明了;转换函数没有参数,因为参数其实就是通过隐式传递的 *this;转换函数必须是成员函数,因为传递的参数就是类对象。

class Demo {
private:
    int value;
    double num;
public:
	operator typeName();
}

C++11 之后可以用 explicit 关键字关闭隐式转换。

小结

没有返回类型的函数:构造函数、析构函数、转换函数;
函数名固定的函数:构造函数和析构函数;
一定没有参数的函数:析构函数和转换函数;
只能出现在类声明中的关键字:friend、explicit;
不能重载的运算符:sizeof . .* :: ?:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值