课程地址: https://www.coursera.org/learn/cpp-chengxu-sheji
文章目录
1.1 内联成员函数和重载成员函数
内联成员函数
成员函数被定义成内联的方法有两种
- inline关键字+成员函数
class A{ inline void func(); }; void A::func() { //自己的代码 }
- 将整个函数体写在类定义内部
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;
}
希望大佬指出其中原因,小弟不胜感激
重载成员函数
重载成员函数和重载函数的区别不是太大,注意两点。
- 返回值类型不能做为区分函数的条件,唯一条件是参数表
- 注意重载函数的二义性,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被调用的三种情况
- 当用一个对象去初始化另一个对象时
ClassName a1(a);
或者ClassName a1 = a;
- 当一个函数的参数是类的对象,当这个函数被调用的时候
class A{
public:
A(const A &a){
cout << "copy constructor" << endl;
};
};
void func(A a){
}
int main()
{
A a1;
func(a1); //这时候copy constructor会被调用
}
- 如果函数的返回值的是类的对象时
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
析构函数特点
- 名字与类名相同,前面在~
- 没有参数和返回值
- 一个类最多只有一个析构函数
note: 用户若没有定义析构函数,则自动生成缺省的析构函数。但是不会释放用户申请的内存
练习
答案C
3.1 静态成员变量和静态成员函数
- 和普通成员变量的区别
- 普通成员变量是一个类变量一份(独立的)
静态成员变量是所有变量一份(共享一份) - 用sizeof计算类的大小时,不会将static定义的变量算作在内
- 普通的成员函数必须依赖于具体的对象才能访问,而静态成员函数不必依赖具体的对象,静态成员变量也是如此
- 必须在定义类的文件中对静态成员变量进行一次说明或者初始化,否则编译能通过,链接不能通过
- 静态成员函数中,不能访问类里面的成员变量。也不能调用类里面成员函数
- 设置静态成员变量和静态成员函数的目的
将某些和类紧密相关的全局变量和全局函数写在类里面,看上去像一个整体,便于维护和理解。
答案B
3.2 成员对象和封闭类的概念
- 成员对象:一个类的成员变量是另一个类的对象
例如:
class Men{};
class Women{};
class People{
Men men; //成员对象
Women women;
};
封闭类:包含成员对象的类叫做封闭类
4.1 友元
一个类的友元函数可以访问该类的私有成员
友元的关系不能继承,也不能传递
4.2 this指针
this指针就是指向其成员函数所作用的对象。
this指针其实特别好理解,本质上就是代表了该对象。
4.3 常量对象,常量成员函数和常引用
关于const后面有专题介绍,这里就先不介绍了