一、内联函数
内联函数的特点:
1)内联函数声明时inline关键字必须和函数定义结合在一起,否则编译器会直接忽略内联请求。
2)C++编译器直接将函数体插入在函数调用的地方
3)内联函数没有普通函数调用时额外的开销(压栈,跳转,返回)
4)内联函数是一种特殊的函数,具有普通函数的特征(参数检查,返回类型等)
5)内联函数由编译器处理,直接将编译后的函数体插入调用的地方
宏代码片段由预处理器处理,进行简单的文本替换,没有任何编译过程
6)C++中的内联编译的限制:
不能存在任何形式的循环语句、不能存在过多的条件判断语句、函数体不能过于庞大、不能对函数进行取址操作、函数内联声明必须在调用语句之前
7)编译器对于内联函数的限制并不是绝对的,内联函数相当于普通函数的优势只是省去了函数调用时压栈,跳转和返回的开销,因此,当函数体的执行开销远大于压栈,跳转和返回所用的开销时,那么内联将毫无意义
#include <iostream>
#define MAX(a,b) ((a)>(b)?(a):(b)) //宏函数可以解决压栈和出栈的开销,但是解决不了参数传递的弊端
using namespace std;
int max(int a, int b){
return (a>b)?a:b;
}
void printAB(int a, int b){
cout << "a = "<< a <<" ,b = " << b << endl;
}
inline void printAB_2(int a, int b){
cout << "a = "<< a <<" ,b = " << b << endl;
}
int main(void){
int a = 10;
int b = 20;
int c = 0;
c = MAX(a, b);
cout << "c = "<< c << endl;
for(int i= 0; i<1000; i++){
a++;
b++;
printAB_2(a, b);//这行函数相当于
// {
// cout << "a = "<< a <<" ,b = " << b << endl;
// }
//即在原位置直接将代码展开,这个展开并不是预处理器展开的
//而是编译器展开的,并且可以校验传参数的正确性
//只不过省略了压栈和出栈的过程
}
#if 0
for(int i= 0; i<1000; i++){
a++;
b++;
printAB(a, b);//会经历1000次压栈和出栈
}
#endif
return 0;
}
二、默认参数和占位参数
#include <iostream>
using namespace std;
void func(int a = 999){//默认参数
cout << "a = " << a << endl;
}
int get_volume(int len , int wight, int hight=10){ //多个参数必须从右向左有默认值
return len * wight * hight;
}
void func(int a, int){ //占位参数 亚元
cout << "a = "<< a <<endl;
}
int main(void){
int value = 10;
func(10);
cout << "volume = " << get_volume(1,1)<< endl;
func(value, 10);
return 0;
}
三、函数重载
重载规则:
1、函数名相同
2、参数个数不同,参数的类型不同,参数顺序不同,均可构成重载
3、返回值类型不同则可以构成重载
重载的底层实现:倾扎(name mangling)技术
#include <iostream>
using namespace std;
//函数的返回值,函数的形参列表(参数个数,参数类型,参数顺序)
//函数重载 函数名相同,参数列表不同
//返回值并不是构成函数重载的条件
int func(int a, char b){
cout << "func1" << endl;
return 0;
}
//如果要是函数重载的话,不要写默认参数,为了避免调用出现函数冲突
int func(int a, int b){
cout << "func2" << endl;
return 1;
}
int func(int a, char* b){
cout << "func3" << endl;
return 1;
}
void print(int a){
cout << "print1" << endl;
cout << a <<endl;
return;
}
void print(double a){
cout <<"print2"<<endl;
cout<< a << endl;
}
void print(char a){
cout <<"print3"<<endl;
cout <<"a = "<< a <<endl;
}
int main(void){
func(1 ,"abd");//func3
print(1);
print(2.0);
print('a');
//1 如果能够严格匹配调用完全匹配的
//2 如果不能严格匹配,调用隐式转换
//3 都匹配不到,调用失败
return 0;
}
四、函数重载和函数指针
#include <iostream>
using namespace std;
int func(int a, int b){
cout << "func1" << endl;
return 0;
}
int func(int a, int b, int c){
cout << "func2" << endl;
return 0;
}
//1.定义一种函数类型(函数指针)
typedef int(MY_FUNC)(int, int);
//2.定义一个指向这种函数类型的指针类型
typedef int(*MY_FUNC_P)(int, int);
int main(void){
//1.
MY_FUNC *fp = NULL;
fp = func;
fp(10,20);//两种方式调用func
(*fp)(10,20);
//2.好理解
MY_FUNC_P fp1 = NULL;
fp1 = func;
fp1(10,20);
//3.比较常用的方式
int(*fp3)(int, int) = NULL;
fp3 = func;
fp3(10,20);
func(10,20);
func(10,20,30);
fp3 = func;//fp3->func(int, int)
//实际上在给函数指针赋值的时候,是会发生函数的重载匹配的
//在调用函数指针的时候,所调用的函数就已经固定了
int(*fp4)(int,int,int) = NULL;
fp4 = func;// fp4 --> func(int, int,int)
fp4(10,20,40);
fp3(10,30);//func(int, int)
//fp3(10,20,30); 无法调用func(int, int,int) 因为指针只指向func1
return 0;
}
五、类和对象
#include <iostream>
using namespace std;
struct Hero{
char name[64];
int sex;
};
class AdvHero{
public://访问控制权限
char name[64];
int sex;
void printHero(){
cout <<"AdnHero-----"<<endl;
cout << "name = " << name <<endl;
cout << "sex = " << sex << endl;
}
};
class Animal{
//{}以内称为类的内部,以外叫外部
public:
//在public下面定义的成员变量和函数 是能够在类的内部和外部都可以访问的
char kind[64];
char color[64];
void printAnimal(){
cout << "kind = " << kind << endl;
cout << "color = " << color << endl;
}
void run(){
cout << kind << " 开始跑步了" <<endl;
}
void write(){
cout << kind << " 开始写字了" << endl;
}
private:
//在private下面定义的成员变量和方法只能在类的内部访问
int age;
};
void printHero(struct Hero &h){
cout << "Hero-----"<<endl;
cout << "name = "<< h.name << endl;
cout << "sex = " << h.sex <<endl;
}
int main(void){
Hero h;//变量类型 变量
strcpy(h.name , "gailun");
h.sex = 1;
printHero(h);
AdvHero Adh;//类名 对象
strcpy(Adh.name , "uzi");
Adh.sex = 1;
Adh.printHero();
cout << "--------------"<<endl;
Animal dog;
strcpy(dog.kind, "dog");
strcpy(dog.color, "yellow");
Animal sheep;
strcpy(sheep.kind, "sheep");
strcpy(sheep.color, "white ");
dog.run();
sheep.write();
return 0;
}
六、类的封装
#include <iostream>
using namespace std;
//一个结构体,默认的访问权限是public
struct Date{
int year;
int month;
int day;
//结构体中也可以写 成员方法
};
//在C++中结构体和类唯一的区别就是默认访问权限不一样
//结构体实际上就是一个类
void init_data(struct Date &d){
cout << "year, month, day"<<endl;
cin >> d.year;
cin >> d.month;
cin >> d.day;
}
//打印date接口
void print_date(struct Date &d){
cout << d.year << "年" << d.month << "月" <<d.day << "日" << endl;
}
//判断是否是闰年
bool is_leap_year(struct Date &d){
if( (d.year%4 ==0) && (d.year % 100 != 0) || (d.year %400 == 0) ){
return true;
}
return false;
}
//一个类的内部,默认的控制访问权限是private
class MyDate
{
public:
//成员方法 成员函数
void init_date(){
cout << "year, month, day" << endl;
cin >> year;
cin >> month;
cin >> day;
}
void print_date(){
cout << year << "年" << month << "月" << day << "日" <<endl;
}
bool is_leap_year(){
if( (year % 4 == 0)&&(year % 100 != 0) || (year % 400 ==0) ){
return true;
}
return false;
}
int get_year(){
return year;
}
void set_year(int new_year){
year = new_year;
}
protected://保护控制权限。在类的继承中与private有区别,在类中与private中是一模一样的
private:
//一般类中的变量(成员变量),存放在private区域中
int year;
int month;
int day;
};
int main(void){
#if 0
Date d1;
init_data(d1);
print_date(d1);
if(is_leap_year(d1)){
cout << "是闰年" << endl;
}
else{
cout << "不是闰年" << endl;
}
#endif
cout << "----------------------------" << endl;
MyDate md;
md.init_date();
md.print_date();
if( md.is_leap_year() ){
cout << "Yes" << endl;
}
else{
cout<< "No" <<endl;
}
//getter,setter
cout << md.get_year() << endl;
md.set_year(2000);
cout << md.get_year() << endl;
return 0;
}
七、面向过程和面向对象
#include <iostream>
using namespace std;
//面向对象
class Dog{
public:
char name[64];
void eat(char *food){
cout << name << "吃" << food <<endl;
}
};
//面向过程
void eat(class Dog &dog, char *food){
cout << dog.name << "吃" << food << endl;
}
int main(void){
Dog dog;
strcpy(dog.name, "狗");
eat(dog, "shit");
dog.eat("shit");
return 0;
}
八、类和对象的一个小例子
例1:求圆的面积和周长(单文件)
#include <iostream>
using namespace std;
//圆的周长
double getCircleGirth(double r)
{
return 2 * 3.14 * r;
}
//圆得面积
double getCircleArea(double r)
{
return 3.14*r*r;
}
//使用面向对象方法实现上面的业务
//类名一般首字母大写
class Circle
{
public:
double getR(){
return m_r;
}
void setR( double r){
m_r = r;
}
double getCircleGirth(){
return 2 * 3.14 * m_r;
}
double getCircleArea(){
return 3.14*m_r*m_r;
}
private:
double m_r;
};
class Circle2
{
public:
double getR(){
return m_r;
}
void setR( double r){
m_r = r;
}
double getCircleGirth(){
m_girth = 2 * 3.14 * m_r;
return m_girth;
}
double getCircleArea(){
m_area = 3.14*m_r*m_r;
return m_area;
}
private:
double m_r;
double m_girth;
double m_area;
};
int main(void){
double r = 10; //圆的半径
double g = 0;//周长
double a = 0;//面积
//面向过程以函数为驱动
g = getCircleGirth(r);
a = getCircleArea(r);
cout << "圆的半径:" << r << endl;
cout << "圆的周长:" << g << endl;
cout << "圆的面积:" << a << endl;
cout << "------------------------------" << endl;
//面向对象以对象为驱动
Circle c1;
c1.setR(10.0);
cout << "圆的半径:" << c1.getR() << endl;
cout << "圆的周长:" << c1.getCircleGirth() << endl;
cout << "圆的面积:" << c1.getCircleArea() << endl;
cout << "------------------------------" << endl;
Circle2 c2;
c2.setR(10.0);
cout << "圆的半径:" << c2.getR() << endl;
cout << "圆的周长:" << c2.getCircleGirth() << endl;
cout << "圆的面积:" << c2.getCircleArea() << endl;
return 0;
}
例2:求圆的面积和周长(多文件)
Circle.h:
#pragma once
//头文件只写声明,不写定义
class Circle
{
public:
//设置半径
void setR(double r);
//得到半径
double getR();
//得到面积
double getArea();
//得到周长
double getGirth();
private:
double m_r;
double m_area;
double m_grith;
};
Circle.cpp:
#include "Circle.h"
//设置半径
void Circle::setR(double r){
m_r = r;
}
//得到半径
double Circle::getR(){
return m_r;
}
//得到面积
double Circle::getArea(){
m_area = m_r * m_r * 3.14;
return m_area;
}
//得到周长
double Circle::getGirth(){
m_grith = 2 * 3.14 * m_r;
return m_grith;
}
main.cpp:
#include <iostream>
#include "Circle.h"
using namespace std;
int main(void){
Circle c;
c.setR(10);
cout << "面积:" << c.getArea() <<endl;
cout << "周长:" << c.getGirth() <<endl;
return 0;
}
例3:求点在圆的内部(单文件)
#include <iostream>
using namespace std;
class Point
{
public:
void setXY(int x, int y){
m_x = x;
m_y = y;
}
int getX(){
return m_x;
}
int getY(){
return m_y;
}
private:
int m_x;
int m_y;
};
class Circle
{
public:
void setXY(int x, int y){
m_x = x;
m_y = y;
}
void setR(int r){
m_r = r;
}
bool IsInsideCircle( Point &p){
if( m_r*m_r > (m_x - p.getX())*(m_x - p.getX()) + (m_y - p.getY())*(m_y - p.getY()) ){
return true;
}
else{
return false;
}
}
private:
int m_x;
int m_y;
int m_r;
};
int main(void){
Point p;
p.setXY(2,2);
Circle c;
c.setXY(0,0);
c.setR(10);
if(c.IsInsideCircle(p)){
cout<< "点 (" << p.getX() << "," << p.getY() << ")在圆内" << endl;
}
else{
cout << "不在圆中" << endl;
}
return 0;
}
例3:求点在圆的内部(多文件)
Point.h:
#pragma once
class Point
{
public:
//设置点坐标
void setXY(int x, int y);
//得到x坐标
int getX();
//得到y坐标
int getY();
private:
int m_x;
int m_y;
};
Circle.h:
#pragma once
#include "Point.h"
class Circle
{
public:
//设置x,y的值,即设置圆心的坐标
void setXY(int x, int y);
//设置圆的半径r
void setR(int r);
//判断点是否在圆内
bool IsInsideCircle(Point &p);
private:
int m_x;
int m_y;
int m_r;
};
Point.cpp:
#include "Point.h"
void Point::setXY(int x, int y){
m_x = x;
m_y = y;
}
int Point::getX(){
return m_x;
}
int Point::getY(){
return m_y;
}
Circle.cpp:
#include "Circle.h"
void Circle::setXY(int x, int y){
m_x = x;
m_y = y;
}
void Circle::setR(int r){
m_r = r;
}
bool Circle::IsInsideCircle( Point &p){
if( m_r*m_r > (m_x - p.getX())*(m_x - p.getX()) + (m_y - p.getY())*(m_y - p.getY()) ){
return true;
}
else{
return false;
}
}
main.cpp:
#include <iostream>
#include "Point.h"
#include "Circle.h"
using namespace std;
int main(void){
Point p;
p.setXY(2,2);
Circle c;
c.setXY(0,0);
c.setR(10);
if(c.IsInsideCircle(p)){
cout<< "点 (" << p.getX() << "," << p.getY() << ")在圆内" << endl;
}
else{
cout << "不在圆中" << endl;
}
return 0;
}
例4:编写C++程序完成下面的功能:
1)定义一个Point类,其属性包括点的坐标,提供计算两点之间的距离方法;
2)定义一个圆形类,其属性包括圆心和半径;
3)创建两个圆形对象,提示用户输入圆心坐标和半径,判断两个圆是否相交,并输出结果。
#include <iostream>
#include <math.h>
using namespace std;
class Point
{
public:
//设置点 x,y的值
void setXY(int x, int y){
m_x = x;
m_y = y;
}
//计算两点之间的距离
double point_distance( Point & another){
double dis;
dis = sqrt( (m_x - another.m_x) * (m_x - another.m_x) + (m_y - another.m_y)*(m_y - another.m_y) );
return dis;
}
private:
int m_x;
int m_y;
};
class Circle
{
public:
//设置圆心
void setXY(int x, int y){
p0.setXY(x, y);
}
//设置半径
void setR(int r){
m_r = r;
}
//判断是否相交
bool isIntersection(Circle &another){
//半径之和
int rr = m_r + another.m_r;
//圆心距离
double dis = p0.point_distance(another.p0);
if(dis <= rr){
return true;
}
else{
return false;
}
}
private:
Point p0;
int m_r;
};
int main(void){
Circle c1;
Circle c2;
int x,y,r;
cout << "输入第一个圆的横坐标:" << endl;
cin >> x;
cout << "输入第一个圆的纵坐标:" << endl;
cin >> y;
c1.setXY(x,y);
cout << "请输入第一个圆的半径:" << endl;
cin >> r;
c1.setR(r);
cout << "输入第二个圆的横坐标:" << endl;
cin >> x;
cout << "输入第二个圆的纵坐标:" << endl;
cin >> y;
c2.setXY(x, y);
cout << "请输入第二个圆的半径:" << endl;
cin >> r;
c2.setR(r);
if(c1.isIntersection(c2)){
cout << "两圆相交" <<endl;
}
else{
cout << "两圆不相交" <<endl;
}
return 0;
}