运算符重载:
运算符重载是一种重新规划运算符的功能,比如我们创建了一个类,而类和类相加不能得到我们想要的结果,所以我们需要重新规划一下运算符的功能。
比如:
class A
{
int x,y;
};
A a,b;
a.x=1;b.x=1;a.y=2;b.y=2;
A c;
c=a+b; //无效,因为a与b都是自己创造的类,如果这么写是没有意义的
如果加一个重载,如:
A::operator+(A c){
A d;
d.x=x+c.x;
d.y=y+c.y;
return d;
}
即可进行a+b操作。
运算符有一元运算符和二元运算符,一元可以直接操作,而二元操作符则需要添加一个参数,作为右操作数,左操作数是当前对象。
不仅如此,还可以重载输出输入运算符,减少代码的繁琐,如果一个类中有过多的数据,比如上面的例子:
A a;
cout<<a.x<<x.y;这样才可以输出全部数据,但如果写一个重载运算:
friend ofstream& operator <<(A a)
{
cout<<a.x<<a.y;
}
这样就可以直接cout<<a;就可以将所有的数据输出了,减少了代码的繁琐。
lambda函数:
这个函数的目的是为了将类似于函数的表达式作为参数,传递给接受函数指针和函数对象参数的函数。
其功能为接受两个参数,返回二者的和。
例子:
void hs()
{
[]{}; //最简lambda函数
int a=3,b=4;
[=]{return a+b};//省略参数列表和返回类型,推断返回为int
auto fun1=[&]{b=a+c}; //无返回类型
auto fun2=[=,&b](int c)->int{return b+=a+c;}; //完整型
}
组合和继承:
组合很简单,是类上用另一个类而已,如:
class A
{
int x;
};
class B
{
A y;
};
B a;
即可进行a.y.x=1;这样的操作,非常简单。
继承:
在已有类的基础上进行拓展,使其成为一个新类,用继承方式创建新类时,要指明这个新类是在哪个已有类的基础上扩展的。
例子:
class A
{
int x,y;
public:
int hs1()
{return x+y;}
};
class B::public A
{
int x,y;
public:
int hs2()
{return x-y;}
}
B a;
a.hs1();a.hs2();
这样在B类中我们就可以进行hs1与hs2的操作,继承了类A中的功能,我们需要注意继承方式。
例子中的继承方式使用的是public,还有protect以及private方式继承。
public成员:能够被程序中的任何函数访问。
private成员:只可以被自己的成员函数和友元访问。
protected被保护成员:是一种特殊的私有成员,不能被全局函数或者其他类中的成员函数访问,但可以被派生类的成员函数和友元函数访问。
多继承:
多继承指的是基类有着多种派生类,派生类与每种基类仍可以看做是单继承。
若三个类的关系是A<---C, B<---C,则c的内存结构就先是A,B。而如果是A,B<--C则C中含有A,B的函数,可以实现A,B功能的接口。
虚函数与多态:
虚函数是一种以virtual关键字申明的函数,是一种类的函数,存在虚函数的类当中都有一个虚表,有一个指向虚表开始位置的指针叫做虚指针,多态是一个接口的多种实现,也就是见人说人话见鬼说鬼话,多态要用虚函数来实现,结合动态绑定,纯虚函数的虚函数要加=0;抽象类包括至少一个虚函数。
例子:
#include <iostream>
using namespace std;
class A
{
public:
virtual void hs()
{
cout << 1 << endl;
}
};
class B:public A
{
public:
void hs()
{
cout << 2<< endl;
}
};
int main()
{
B b;
A *aa= &b;
A& a=b;
aa->hs();
a.hs();
A aaa;
A* c = &aaa;
c->hs();
return 0;
}
主要是看指针指向哪个类,就输出哪个类的所对应的虚函数或者函数名,这样就实现了见人说人话见鬼说鬼话。
纯虚函数:
class A
{
virtual void hs() = 0;
protected :
string s;
};
class B: public A
{};
纯虚函数没有函数体,那个=0并不是赋值,而是说明这是一个纯虚函数,因为这是一个说明函数,所以要有分号,纯虚函数不具备函数功能,仅有一个函数名,所以不能被调用,如果含有纯虚函数的类被调用,而派生类依然没有定义纯虚函数,则此纯虚函数在派生类中还是纯虚函数。
纯虚函数的作用是在基类事先为派生类创造一个函数的名字,可以让派生类对其定义。如果在基类中没有保留函数的名字,就无法实现多态性。