coursera---C++程序设计重点笔记--week3

课程地址: https://www.coursera.org/learn/cpp-chengxu-sheji

1.1 内联成员函数和重载成员函数

内联成员函数

  • 成员函数被定义成内联的方法有两种
  1. inline关键字+成员函数
    class A{
    	inline void func();
    };
    void A::func()
    {
    //自己的代码
    }
    
  2. 将整个函数体写在类定义内部
    class A{
     void func(){
    //自己的代码
     };
    };
    

这里设计一个实验去比较这三种方法的运行时间。

  • 函数1(func1):inline关键字定义的内联函数
  • 函数2(func2):函数写在类内部定义的内联函数
  • 函数3(func3):非内联函数
    结论 没有结论,每次运行的结论都不一样。而且有时候是不用内联的函数运行时间短。
#include <iostream>
#include <stdio.h>
#include "time.h"
using namespace std;

class A{
public:
	inline void func1();
	void func2()
	{
		int i = 10;
		while (i--);
	};
	void func3();
};
void A::func1()
{
	int i = 10;
	while (i--);
}
void A::func3()
{
	int i = 10;
	while (i--);
}

int main(int argc, char * argv[])
{
	//内联函数运行时间比较
	A aa;
	const int run_cnt = 100000;
	clock_t starts = clock();
	for (int i = 0; i < run_cnt; i++)
		aa.func1();
	clock_t ends = clock();
	printf("func1 run time: %.10f \n",(double)(ends - starts) / CLOCKS_PER_SEC);
	 

	starts = clock();
	for (int i = 0; i < run_cnt; i++)
		aa.func2();
	ends = clock();
	printf("func2 run time: %.10f \n", (double)(ends - starts) / CLOCKS_PER_SEC);
	
	starts = clock();
	for (int i = 0; i < run_cnt; i++)
		aa.func3();
	ends = clock();
	printf("func3 run time: %.10f \n", (double)(ends - starts) / CLOCKS_PER_SEC);

	while(1);
	return 0;
}
希望大佬指出其中原因,小弟不胜感激

重载成员函数

重载成员函数和重载函数的区别不是太大,注意两点。

  1. 返回值类型不能做为区分函数的条件,唯一条件是参数表
  2. 注意重载函数的二义性,c++会报二义性的错误

1.2 构造函数

构造函数的成员函数的一种,不能有返回值(void也不行)

  • 默认的构造函数
    默认的构造函数没有参数,里面什么都没有。自己写了构造函数之后就不会有默认的构造函数了(这句有疑问???)
"默认的构造函数会接受以下四种定义方式"
class A{
};
A a1;
A a2();
A a3(a1);
A a4 = a1;
//以上四种定义方式都是可以的

不管以任何形式定义一个对象,都需要构造函数初始化

  • 多个自定义构造函数重载
    证明:自定义构造函数之后,默认的构造函数任然在使用
class A{
public:
	A(){
		cout << "constructor A()" << endl;
	};	
};

int main(int argc, char * argv[])
{
	A a;
	cout << "step1" << endl;
	A a1();
	cout << "step2" << endl; 
	A a2(a);
	cout << "step3" << endl;
	A a3 = a;
	system("Pause");
}
//运行结果
constructor A()
step1
step2
step3
Press any key to continue . . .
"可以看到虽然定义了构造函数,但是之前的构造函数还在"
"比较匪夷所思的是: 构造函数写的是A(),但是A a1();却不调用自定义构造函数,反而是A a;调用"

重载规则一模一样,具体的例子可以参考stl中vector的定义
vector构造函数: http://www.cplusplus.com/reference/vector/vector/vector/
多说一句:正是由于有了重载技术,vector类才能在保证兼容性的基础上不断的完善。

  • 构造函数在数组中的使用
    比如要用vector定义二维数组:
    vector<int> a[2] = {vector<int>(2,1),vector<int>(3,1)};
    {}里的第一个参数表示对数组的第一个参数进行初始化的参数。

对于自定义的构造函数:可以这样初始化
A a1[2] = {1,2} A a1[2] = {{1},{2}}

2.1 复制构造函数copy constructor

基本概念

  • copy constructor基本形式
    ClassName (const ClassName &old_obj);只有一个参数,即同类对象的引用。
    note:只允许用类的应用做参数
  • copy constructor被调用的三种情况
  1. 当用一个对象去初始化另一个对象时
    ClassName a1(a); 或者 ClassName a1 = a;
  2. 当一个函数的参数是类的对象,当这个函数被调用的时候
class A{
public:
	A(const A &a){
		cout << "copy constructor" << endl;
	};
};
void func(A a){
}
int main()
{
	A a1;
	func(a1); //这时候copy constructor会被调用
}
  1. 如果函数的返回值的是类的对象时
class A{
public:
	int v;
	A(const A &a){
		v = a.v;
		cout << "copy constructor" << endl;
	};
};
A func(){
	A a;
	a.v = 10;
	return a;
}
int main()
{
	A a1;
	cout << func().v << endl; //这时候copy constructor会被调用
}

为什么要自己写copy constructor

to be continue…

练习

答案A
在这里插入图片描述

2.2 类型转换构造函数

特殊的构造函数
目的:类型的自动转换,将一个其他类型的数据转换成类的对象
特点:只有一个参数,不是copy constructor
转换构造函数是对构造函数的重载

class Complex{
public:
	double real;
	double img;
	Complex(){};
	Complex(double re){
		real = re;
		cout << "conversion construtor" << endl;
	};
	Complex(double re,double im){
		real = re;
		img = im;
		cout << "construtor" << endl;
	};
	
};
int main()
{
	Complex a1(10,20);
	a1 = 9; //这里就调用了一次conversion constructor。
	//相当于把9变成了一个Complex对象
	Complex a2 = 9; //这里也调用了conversion constructor。
}

"输出结果"
constructor
conversion constructor
conversion constructor

练习

答案D
在这里插入图片描述

2.3 析构函数destructor

析构函数特点

  1. 名字与类名相同,前面在~
  2. 没有参数和返回值
  3. 一个类最多只有一个析构函数

note: 用户若没有定义析构函数,则自动生成缺省的析构函数。但是不会释放用户申请的内存

练习

答案C
在这里插入图片描述

3.1 静态成员变量和静态成员函数

  • 和普通成员变量的区别
  1. 普通成员变量是一个类变量一份(独立的)
    静态成员变量是所有变量一份(共享一份)
  2. 用sizeof计算类的大小时,不会将static定义的变量算作在内
  3. 普通的成员函数必须依赖于具体的对象才能访问,而静态成员函数不必依赖具体的对象,静态成员变量也是如此
  4. 必须在定义类的文件中对静态成员变量进行一次说明或者初始化,否则编译能通过,链接不能通过
  5. 静态成员函数中,不能访问类里面的成员变量。也不能调用类里面成员函数
  • 设置静态成员变量和静态成员函数的目的
    将某些和类紧密相关的全局变量和全局函数写在类里面,看上去像一个整体,便于维护和理解。
    答案B
    在这里插入图片描述

3.2 成员对象和封闭类的概念

  • 成员对象:一个类的成员变量是另一个类的对象
    例如:
class Men{};
class Women{};
class People{
	Men men;  //成员对象
	Women women; 
};

封闭类:包含成员对象的类叫做封闭类

4.1 友元

一个类的友元函数可以访问该类的私有成员
友元的关系不能继承,也不能传递

4.2 this指针

this指针就是指向其成员函数所作用的对象。
this指针其实特别好理解,本质上就是代表了该对象。

4.3 常量对象,常量成员函数和常引用

关于const后面有专题介绍,这里就先不介绍了

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值