一.内联函数
(1).函数调用的回顾:
函数的调用有时间和空间上的开销,程序在执行一个函数之前需要做一些工作,实参,局部变量,返回值等若干寄存器入栈,然后才能执行函数体,执行完毕之后,还要回收空间(出栈)等,需要时间和空间上的开销
(2).c语言中
<1>在复制代码的时候,容易出现意想不到的边界效应
可以使用宏函数来解决这个问题,编译器通过直接替换代码的方式,省去了入栈,出栈等1开销,缺点就是缺少边界检查,但是在效率上还是可取的
#define MAX(A,B) (A>B)?A:B
<2>使用宏,无法进行调试
<3>使用宏,无法访问类的私有成员
(3).c++中
推荐使用内联函数代替宏函数,内联函数,类似于宏函数体的替换,这种在函数调用时嵌入函数体的函数成为内嵌函数,也称为内联函数
inline int myfun(int a,int b)
{
return (a > b) ? a : b;
}
内联函数的特点和缺点
1>不能存在任何形式的循环语句
2>不能存在过多的条件判断语句
3>函数体不能过于庞大(调用内联函数就是为了省去入栈出栈时的开销,若远大于入栈出栈的开销,内联函数将会变得毫无意义)
4>不能对函数进行取地址操作
5>函数内联声明必须在调用语句之前
二.c++中的默认参数
(1)概念:
c++中,允许定义函数参数的时候给其一个默认值,在使用该函数的时候,如果不传参,可以直接使用该默认值
(2)例:
#include <iostream>
using namespace std;
int MAX(int a,int b,int c = 100)
{
cout << "a = " << a << " " << "b = " << b << " c = " << c <<endl;
}
int main(int argc, const char *argv[])
{
int x = 1,y = 2;
MAX(x,y);
return 0;
}
***ps:1.默认参数在定义的时候,从左往右,只要有一个参数为默认参数,那么它右边所有参数都必须为默认参数
2.若未传参,则使用默认参数,若传参,则使用传的参数
三.占位参数
(1)概念:
占位参数只有参数类型声明,没有参数变量声明,一般情况下,无法在函数体内部使用占位参数
(2)例:
#include <iostream>
using namespace std;
void add(int a,int b,int = 0)
{
cout << "a + b = " << a + b << endl;
}
void add1(int a,int b,int)
{
cout << "a + b = " << a + b << endl;
}
int main(int argc, const char *argv[])
{
int x = 1,y = 2;
add(x,y);
add(x,y,3);
return 0;
}
四.函数重载
(1)概念:
在实际开发的时候,有时需要实现几个功能类似的函数,在c语言中,不得不定义多个函数名不同的函数去实现,在c++中,可以利用函数重载,实现一类函数功能,使用同一个函数名实现
(2)函数重载的条件:
1.函数名相同
2.函数的参数类型,个数,顺序不同
3.和返回值类型无关
(3)例:
#include <iostream>
using namespace std;
void Swap(int &x,int &y)
{
cout << "int int" << endl;
int tmp = x;
x = y;
y = tmp;
}
void Swap(int &x,double &y)
{
cout << "int double" << endl;
int tmp = x;
x = y;
y = tmp;
}
void Swap(int &x,int &y,int &z)
{
cout << "int int int" << endl;
int tmp = x;
x = y;
y = z;
}
void Swap(double &x,int &y)
{
cout << "double int" << endl;
int tmp = x;
x = y;
y = tmp;
}
int main(int argc, const char *argv[])
{
int a = 1,b = 2,c = 3;
double d = 3.14;
Swap(a,d);
Swap(a,b);
Swap(d,c);
Swap(a,c,b);
return 0;
}
五.函数重载的二义性
#include <iostream>
using namespace std;
void add(int a,int b)
{
cout << a + b << endl;
}
void add(int a,int b,int c = 100)
{
cout << a + b << endl;
}
int main(int argc, const char *argv[])
{
int x = 1,y = 2;
add(x,y);
return 0;
}
六.c++的动态内存分配
(1)new/delete
c语言中使用malloc free 函数
c++中使用new/delete 关键字,但是malloc和free仍然可以使用
(2)两者区别
C语言中:malloc是一个函数,返回值类型是void*类型
c++中:new和delete是关键词,返回值类型是申请对象的类型,可以初始化
(3)例:
#include <iostream>
using namespace std;
int main(int argc, const char *argv[])
{
int *p = new int;
*p = 100;
cout << "*p = " << *p << endl;
delete p;
p = NULL;
int *q = new int(200);
cout << "*q = " << *q << endl;
delete q;
q = NULL;
int *q2 = new int[5]{1,2,3,4,5};
for(int i = 0;i < 5;i++)
{
cout << q2[i] << " ";
}
cout << endl;
delete []q2;
q2 = NULL;
return 0;
}
七.多维数组的创建和释放
例子:二维数组的动态创建,申请存放二维数组int a[3][4]
#include <iostream>
using namespace std;
int main(int argc, const char *argv[])
{
int **a = new int *[3];//二级指针指向数组首地址
for(int i = 0;i < 3;i++)
{
a[i] = new int[4];
}
for(int i = 0;i < 3;i++)
{
delete []a[i];
}
delete []a;
return 0;
}
八.
8.1面向对象编程
优点:
1.开发速度快,如果开发某个功能,实现起来很麻烦,可以使用现有的类快速实现
2.封装性和抽象性:结构清晰,很标准,规范化,易于理解,可读性强
3.继承:便于扩展,改动小,大框架不需要改动
4.易维护:维护成本低
5.质量高:被反复测试,可以快速的满足各项功能开发的需求
6.效率高:依赖于抽象,对于具体的实现统一了接口
缺点:
相比于c语言,运行效率会下降10%左右
8.2类和对象的使用
#include <iostream>
#include <cstring>
using namespace std;
class Student1
{
public:
int age;
char name[32];
void print()
{
cout << "age = " << age << " " << "name = " << name << endl;
}
};
int main(int argc, const char *argv[])
{
Student1 s1;
s1.age = 20;
strcpy(s1.name,"zhangsan");
s1.print();
return 0;
}
8.3类的访问权限
访问级别由public protected private三个关键字组成
public:共有属性,凡是在它下面定义的,类的内部和外部都可以访问
protected:保护属性,凡是在它下面定义的,在继承关系中,可以在子类访问
private:私有属性,凡是在它下面定义的,只能在类的内部访问
#include <iostream>
using namespace std;
class Test
{
private:
int a;
void f1(){}
protected:
int b;
void fa(){}
public:
int c;
void f3(){}
};
int main(int argc, const char *argv[])
{
Test t1;
t1.c = 200;
cout << "t1.c = " << t1.c << endl;
return 0;
}
8.4类中的元素说明
#include <iostream>
using namespace std;
class Circle
{
private:
int m_r;
double m_s;
public:
void SetR(int r)
{
m_r = r;
}
double GetS()
{
m_s = 3.13159 * m_r * m_r;
return m_s;
}
};
int main(int argc, const char *argv[])
{
Circle c1;
c1.SetR(100);
cout << "s = " << c1.GetS() << endl;
return 0;
}
练习:
设计一个圆形类和一个点类,计算点在圆外,园内,还是圆上(点和圆的关系)
1>点: 属性:横坐标和纵坐标 方法:点和点的距离 2>圆: 属性:圆心,半径 方法:设置圆心和半径 判断点和圆的关系
#ifndef _CIRCLE_H_ #define _CIRCLE_H_ class Point { private: int m_x; int m_y; public: void SetXY(int x,int y); int Distance(Point &p); }; class Circle { private: Point m_center; //圆心 int m_r; public: void setC(int x,int y,int r); bool Judge(Point &p); }; #endif
#include "circle.h" int main(int argc, char const *argv[]) { Point p; p.SetXY(0,3); Circle c1; c1.setC(0,0,3); if(c1.Judge(p)) { cout<<"点在圆外或者圆上"<<endl; } else { cout<<"点在圆内"<<endl; } return 0; }
#include "circle.h" void Point::SetXY(int x,int y) { this->m_x = x; this->m_y = y; } int Point::Distance(Point &p) { int dis = (p.m_x - m_x)*(p.m_x - m_x) + (p.m_y - m_y)*(p.m_y - m_y); return dis; } void Circle::setC(int x,int y,int r) { m_center.SetXY(x,y); m_r = r; } bool Circle::Judge(Point &p) { if(p.Distance(m_center) >= m_r*m_r) { return true; } else { return false; } }
8.6 对象的构造和析构
(1)构造函数
在c++中,有一种特殊的成员函数,名字和类名相同,没有返回值,不需要用户显示调用(也不能调用),而是在创建的时候自动执行
几点说明:
1.构造函数的名字和类型必须相同
2.构造函数不能有返回值,不能有return语句
3.创建对象的时候自动执行,不能手动调用
4.主要用于对类的成员进行赋值
#include <iostream>
using namespace std;
class Array
{
private:
int size; //数组的容量
int *data; //数组首地址
public:
Array(); //无参构造函数
void setVal(int Index,int value);
int GetVal(int Index);
~Array();
};
Array::Array()
{
cout<<"Array的无参构造函数"<<endl;
size = 5;
data = (int *)malloc(sizeof(int)*size);
}
void Array::setVal(int Index,int value)
{
data[Index] = value;
}
int Array::GetVal(int Index)
{
return data[Index];
}
Array::~Array()
{
cout<<"Array的析构函数"<<endl;
if(data != NULL)
{
free(data);
data = NULL;
}
}
int main(int argc, char const *argv[])
{
Array a1; //创建对象,自动调用构造函数
for(int i = 0 ; i < 5;i++)
{
a1.setVal(i,i+1);
}
for(int i = 0; i < 5;i++)
{
cout<<a1.GetVal(i)<<" ";
}
cout<<endl;
return 0;
}