文章目录
一、多态
派生类
重写原类
的功能
示例:
class A //原类
{
show()
{
cout<<“~~~~~A”;
}
};
Class B:public A //派生类
{
show() //重写函数
{
cout<<“~~~~~~B”;
}
};
A a;
B b;
a.show();
b.show();
使用时,a.show()
显示~~~~~A
, b.show()
显示~~~~~~B
,也就是派生类 重写的show
覆盖 原类的show
。
正常的情况就是 重写的功能
覆盖 原功能
,但是加入指针就会出现问题,因为C++中允许原类的指针 指向 派生类的地址。
看下面实例代码:
#include <iostream>
using namespace std;
class A
{
public:
void show()
{
cout << "AAAAAAAAAA" << endl;
}
};
class B:public A
{
public:
void show()
{
cout << "BBBBBBBBBB" << endl;
}
};
int main()
{
B b;
A *a = &b; //原类指针 获取 派生类地址
a->show();
return 0;
}
打印结果为:
可以看出明明是派生类对象,因为原类指针的问题,打印出原类的功能函数。
1、虚函数
为解决上述多态问题,引入C++引入虚函数,具体就是在原类功能前面加入
virtual
关键字就行了
将上述的实例代码改为
#include <iostream>
using namespace std;
class A
{
public:
virtual void show()
{
cout << "AAAAAAAAAA" << endl;
}
};
class B:public A
{
public:
void show()
{
cout << "BBBBBBBBBB" << endl;
}
};
int main()
{
B b;
A *a = &b;
a->show();
return 0;
}
打印结果为:
打印正常。
2、纯虚函数
形式类似于:
virtual void func() = 0;
,即不写实现过程,让函数等于0。
作用:常作为接口,功能实现交给派生类实现。
3、虚析构函数
析构函数前加
virtual
关键字,落实到问题上其实还是还是指针的问题,具体看实例代码
实例代码:
#include <iostream>
using namespace std;
class A
{
public:
~A()
{
cout << "AAAAAAAAAA" << endl;
}
};
class B:public A
{
public:
~B()
{
cout << "BBBBBBBBBB" << endl;
}
};
int main()
{
A *a = new B;
delete a;
return 0;
}
打印结果:
可以看出只执行了原类的析构函数,派生类的析构函数没有执行,这样有时候会导致内存不完全释放的问题。
加上virtual后的打印结果:
二、异常
C语言中,我们经常通过判断函数的返回值,来判断程序是否出错。但这样会出现一种情况,就是当
函数求出的返回值
与函数出错时的返回值
一样时,我们不知道是程序是否出错。
C++使用异常来升级程序执行错误的处理,使用方法看下面的示例代码。
示例代码:
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
int myatoi(const char *str)
{
if(*str<'0' || *str>'9') //转化的字符串第一个字符不是数字时
throw "wrong arg!!!!"; //抛出错误,字符串为主函数中的p
else
return atoi(str);
}
int main()
{
try //程序没有出错时
{
int data = myatoi("asdfas");
cout<< data <<endl;
}
catch(const char *p) //程序出错时的处理
{
cout << p << endl; //打印抛出的错误
}
}
1、exception类
C++标准库给出的异常处理类,我们使用其派生类来进行异常处理,具体以下面的示例代码所示。
示例代码:
#include <iostream>
#include <stdlib.h>
#include <exception>
using namespace std;
class myexception:public exception //使用exception派生类
{
public:
const char *what() const throw()
{
return "aaaaaa"; //出错处理自定义
}
};
int myatoi(const char *str)
{
if(*str < '0' || *str > '9')
throw myexception(); //抛出错误
else
return atoi(str);
}
int main()
{
int a;
try //程序没有出错时
{
a = myatoi("adada");
}
catch(myexception e) //异常处理
{
cout << e.what() << endl; //打印出错信息
}
return 0;
}
使用时,一定记得要加头文件
2、预定义异常类
标准库包含的异常处理类
三、转换函数
对象之间的类型转换
1、标准转换函数
- reinterpret_cast
reinterpret_cast<new type>(expression)
将一个类型的指针转换为另一个类型的指针,它也允许从一个指针转换为整数类型
- const_cast
const_cast< new type>( expression)
const指针与普通指针间的相互转换,注意:不能将非常量指针变量转换为普通变量
- static_cast
static_cast<new type>(expression)
主要用于基本类型间的相互转换,和具有继承关系间的类型转换
- dynamic_cast
dynamic_cast<newtype>(expression)
只有类中含有虚函数才能用dynamic_cast;仅能在继承类对象间转换
dynamic_cast具有类型检查的功能,比static_cast更安全
2、自定义转换函数
自定义转换类型的实现,一般形式为:operator 类型(){ 实现步骤}
示例代码:(包含标准转化函数)
#include <iostream>
#include <exception>
using namespace std;
class A
{
public:
virtual void show()
{
cout << "xxxxxxx" << endl;
}
operator int() //重定义int类型的强转
{
return 10;
}
};
class B:public A
{
void show()
{
cout << "aaaaaaa" << endl;
}
};
int main()
{
#if 0
int a;
char *P = reinterpret_cast<char *>(&a);
return 0;
#endif
#if 0
const int b = 100;
int *p = const_cast<int *>(&b);
#endif
#if 0
A a;
B &p = static_cast<B &>(a);
#endif
#if 0
try{
A a;
B &p = dynamic_cast<B &>(a);
}
catch(bad_cast e)
{
cout << e.what() << endl;
}
#endif
A a;
int t = a; //对象a自动转化为int类型,并调用int转换函数
cout << a << endl;
}
3、隐式转换 – explicit
示例:
#include <iostream>
using namespace std;
class mempool
{
public:
explicit mempool(int size)
{
data = new char[size];
cout<< "cccccccccc" <<endl;
}
~mempool()
{
delete [] data;
}
private:
char *data;
};
int main()
{
// mempool a(100);
mempool a = 100;
}
四、模板
1、类型模板
类似于C语言中的
typedef
与define
功能
使用形式为:template < typename T>
使用实例:
#include <stdio.h>
#include <iostream>
using namespace std;
template<typename XXX>
XXX add(XXX a, XXX b)
{
return a+b;
}
int main()
{
cout<< add(1, 2) <<endl; //自动转化为int类型相加
cout<< add(1.1, 2.3) <<endl; //自动转化为double类型相加
}
2、模板特化
模板类的特殊情况
示例代码:
#include <stdio.h>
#include <iostream>
using namespace std;
#if 0
int add(int a, int b)
{
return a+b;
}
double add(double a, double b)
{
return a+b;
}
#endif
template<typename XXX>
XXX add(XXX a, XXX b)
{
return a+b;
}
template <> //上面模板内容的特殊情况,这里自定义处理
bool add(bool a, bool b)
{
if(a == true && b == true)
return true;
return false;
}
int main()
{
cout<< add(1, 2) <<endl;
cout<< add(1.1, 2.3) <<endl;
cout<< add(true, false) <<endl;
cout<< add(true, true) <<endl;
}