引用类型
在c++中这样定义引用int &b = a; //定义引用时 必须同时定义引用的对象
引用相当于指针,当时跟指针不同的是引用的并不占内存,也就是内存中并没有b
引用的作用可以给函数用作参数,在修改参数的值同时,相当于修改了原来的引用对象
#include<iostream>
using namespace std;
void add(int& a)
{
a = a+5; //在这了使用了引用类型的参数,直接就会修改引用对象的值
}
int _tmain(int argc, _TCHAR* argv[])
{
int a = 0;
int &b = a; //定义引用时 必须同时定义引用的对象
add(b);
cout << "a=" << a << endl;
getchar();
return 0;
}
内联函数
内联函数:为了提高调用简单函数的运行效率,编译器不会为这种简单的函数分配堆栈.
内联函数体内不能有循环语句和switch语句
// test.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<iostream>
using namespace std;
const double PI = 3.14159265358979;
inline double calArea(double radius)
{
return PI*radius*radius;
}
int _tmain(int argc, _TCHAR* argv[])
{
double r = 3.0;
double area = calArea(r);
cout << "a=" << area << endl;
getchar();
return 0;
}
带默认参数值得函数
默认的参数值只能都在右边,不能间隔.
#include "stdafx.h"
#include<iostream>
using namespace std;
//int add(int a=3,int b,int c=6) 这是错误的定义形式 有默认值的必须都在右边 中间不能有没有默认值的参数
//另外一种情 如果函数时申明在头文件 函数体在别的文件 那么在申明时给出默认值即可,函数实现体里面不用再次给出默认值
int add(int a,int b=5,int c=6)
{
return a + b + c;
}
int _tmain(int argc, _TCHAR* argv[])
{
int count=add(3);
cout << "a=" << count << endl;
getchar();
return 0;
}
函数重载
c++语法里面两个函数有相同的函数名,而函数的参数不同.这就是函数重载
#include "stdafx.h"
#include<iostream>
using namespace std;
int add(int a)
{
return a + 3;
}
int add(int a,int b)
{
return a + b;
}
double add(double a, double b)
{
return a + b;
}
int _tmain(int argc, _TCHAR* argv[])
{
int count=add(3);
cout << "a=" << count << endl;
getchar();
return 0;
}
面向对象
面向对象程序的特点: 抽象 封装 继承 多态
构造函数
#include "stdafx.h"
#include<iostream>
using namespace std;
class Student
{
private:
int age;
char name[20];
public:
Student();
Student(int age);
Student(char *name,int age);
void SetAge(int age);
void SetName(char *name);
};
//默认构造函数
Student::Student()
{
this->age = 0;
memset(this->name,0,sizeof(this->name));
}
//带参数的构造函数
Student::Student(int age) :age(age)//直接赋值 比在函数内部赋值效率更高
{
}
//带参数的构造函数
Student::Student(char *name, int age)
{
this->age = age;
strcpy_s(this->name, sizeof(this->name), name);
}
//设置年龄
void Student::SetAge(int age)
{
this->age = age;
}
//设置名字
void Student::SetName(char* name)
{
strcpy_s(this->name, sizeof(this->name), name);
}
int _tmain(int argc, _TCHAR* argv[])
{
char *name = "dale";
//定义一个类的对象,会自动调用构造函数
Student stu(name,20);
getchar();
return 0;
}
复制构造函数
//复制构造函数 利用已经存在类对象来初始化另外一个对象
Student(const Student &stu); //类内申明
Student::Student(const Student &stu) //类外实现
{
this->age = stu.age;
strcpy_s(this->name, sizeof(this->name), stu.name);
}
析构函数
如果不定义析构函数,那么编译器会自动定义.在析构函数中释放在类中使用的资源,例如在堆中分配的内存,打开的文件句柄等等
在这个类对象销毁时,会自动调用析构函数.
~Student(const Student &stu); //类内申明
Student::~Student() //类外实现
{
//释放资源
}
静态数据成员
class Student
{
private:
int age;
char name[20];
static int num; //在类里定义一个静态成员变量
public:
Student();
Student(int age);
Student(char *name,int age);
//复制构造函数 利用已经存在类对象来初始化另外一个对象
Student(const Student &stu);
~Student();
void SetAge(int age);
void SetName(char *name);
};
//静态成员变量的初始化必须在类外
int Student::num = 0;
静态函数成员
class Student
{
private:
int age;
char name[20];
static int num;
public:
Student();
Student(int age);
Student(char *name,int age);
//复制构造函数 利用已经存在类对象来初始化另外一个对象
Student(const Student &stu);
~Student();
void SetAge(int age);
void SetName(char *name);
static void ShowNum()
{
cout << num << endl;//静态函数成员只能访问类内的静态数据成员
}
};
友元函数
class Student
{
private:
int age;
char name[20];
static int num;
public:
Student(char *name,int age);
friend void DisplayAge(const Student &stu); //开放一个权限给类外的函数使用类的私有成员变量
};
void DisplayAge(const Student &stu)
{
cout << stu.age << endl;
}
vector
c++标准库中的数组模板,可以定义任何类型的数组.
定义语法:vector<元素类型> 数组对象名(数组长度);
vector <int >arr(5);
继承
公有继承:
派生类中的成员函数可以访问基类的public和protect成员,
派生类对象也可以访问基类的public和protect成员
私有继承:
私有继承:基类的public和protected成员都以privete身份出现在派生类中
派生类中的成员函数可以访问基类的public和protect成员,
派生类对象不可以访问基类的任何成员
保护继承:基类的public和protected成员都以protected身份出现在派生类中
派生类中的成员函数可以访问基类的public和protect成员
派生类对象:不能访问从基类继承的任何成员.
私有继承和保护继承的区别:
私有继承如果再派生子类的话,其父类任何权限的成员都不能再次被访问.因为其父类的成员在其类中的访问权限是private.
而保护继承的话,其父类的成员在其类中的访问权限是protected,那么使用公有和保护继承还是可以使用其父类的public和protected成员的.
运算符重载
c++几乎可以重载全部的运算符, 不能重载的运算符有: '.' '.*' '::' '?:'
重载为类成员的运算符函数定义形式:
函数原型 operator 运算符(形参)
{
}
参数个数=原操作数个数-1(后置++ – 除外)
双目运算符重载
//在类里面申明运算符重载 +是双目运算符,所以在这里只需要一个参数.
Student operator +(const Student&stu);
//在类外的实现
Student Student::operator + (const Student& stu)
{
return Student(this->age+stu.age);
}
单目运算符重载
//在类里面申明运算符重载 ++是单目运算符,所以不需要参数.
//++分为前置和后置的,这里为了区分,采用了函数重载的形式 后置++给了一个参数 但是不会使用它
Student operator ++();
Student operator ++(int num);
//类外实现
Student Student::operator ++ ()
{
return Student(++this->age);
}
Student Student::operator ++ (int num)
{
return Student(this->age++);
}
//测试重载后的前置++ 和后置++
int _tmain(int argc, _TCHAR* argv[])
{
Student stu1(10),stu2(10);
(stu1++).DisplayAge();
(++stu2).DisplayAge();
getchar();
return 0;
}
运算符重载为非成员函数
运算符重载为非成员函数的规则:
函数的形参代表依自左至右次序排列的各操作数。
重载为非成员函数时 参数个数=原操作数个数(后置++、–除外)
至少应该有一个自定义类型的参数。(不能全部都是基本类型)
后置单目运算符+ +和–的重载函数,形参列表中要增加一个int ,
但不必写形参名。
如果在运算符的重载函数中需要操作某类对象的私有成员,可以将
此函数声明为该类的友元。
//类内申明为友元函数
friend Student operator+(const Student& stu1, const Student& stu2);
friend ostream& operator<<(ostream& out,const Student &stu);
//类外实现
Student operator+(const Student& stu1, const Student& stu2)
{
return Student(stu1.age+stu2.age);
}
ostream& operator<<(ostream& out, const Student &stu)
{
out << "age=" << stu.age << endl;
return out;
}
虚函数
#include "stdafx.h"
#include<iostream>
using namespace std;
class base{
public:
void display() const
{
cout << "base" << endl;
}
};
class derive1:public base{
public:
void display() const
{
cout<< "derive1" << endl;
}
};
class derive2 :public base{
public:
void display() const
{
cout << "derive2" << endl;
}
};
void pubDisplay(base* ptr)
{
ptr->display();
}
int _tmain(int argc, _TCHAR* argv[])
{
base b;
derive1 d1;
derive2 d2;
pubDisplay(&b);
pubDisplay(&d1);
pubDisplay(&d2);
getchar();
return 0;
}
输出结果,
这显然不是我们想要的,我们想要不同的指针类型去调用这个通用的输出函数,会输出不同的结果.
这就需要在定义基类时使用虚函数,这样就能实现函数运行时多态.
//在基类的函数定义时使加上virtual即可
virtual void display() const //子类在调用带有virtual的函数时,会先在子类查找是否重写了该函数,如果有则调用子类的,没有就调用父类的.
{
cout << "base" << endl;
}
虚表和动态绑定
当对象里面有虚基类函数时,会在对象头部生成一个虚表的指针,该指针指向一个函数表.
抽象类
纯虚函数
纯虚函数是一个在基类中声明的虚函数 ,它在该基类中没有定义具体的操作内容, 要求各派生类根据实际需要定义自己的版本,
纯虚函数的声明格式为:virtual函数类型函数名(参数表) = 0;
带有纯虚函数的类称为抽象类