C++——多态、异常、转化函数
目录
一、多态
二、异常
三、转换函数
3.1标准转换函数
3.2自定义转换函数
3.3隐式转换(explicit)
封装Thread类
一、多态
c++支持用基类的指针指向派生类。
#include <iostream>
using namespace std;
class A{
public:
A(){ }
~A(){ cout<<"A~~~~~~~~~"<<endl; }
void show()
{
cout<<"AAAAAAAAAAAAA"<<endl;
}
};
class AX:public A{
public:
~AX(){ cout<<"AX~~~~~~~~~"<<endl; }
void show()
{
cout<<"BBBBBBBBBBBBB"<<endl;
}
};
int main()
{
// AX a;
// AX *p = new AX;
// delete p;
//A *p = new AX;
//delete p;
/*
A a;
a.show();
AX b;
b.show();
*/
#if 1
AX a;
AX *q = &a;
A *p = &a;
q->show();
p->show();
#endif
}
谁的指针就show谁,他们指向的都是派生类的对象,但是真正执行按指针来。
谁先结束谁先执行析构函数
当我们把基类写成虚函数后,就变成了认对象不认指针。
#include <iostream>
using namespace std;
class A{
public:
A(){ }
~A(){ cout<<"A~~~~~~~~~"<<endl; }
virtual void show()
{
cout<<"AAAAAAAAAAAAA"<<endl;
}
};
class AX:public A{
public:
~AX(){ cout<<"AX~~~~~~~~~"<<endl; }
void show()
{
cout<<"BBBBBBBBBBBBB"<<endl;
}
};
int main()
{
// AX a;
// AX *p = new AX;
// delete p;
//A *p = new AX;
//delete p;
/*
A a;
a.show();
AX b;
b.show();
*/
#if 1
AX a;
AX *q = &a;
A *p = &a;
q->show();
p->show();
#endif
}
加上virtual就变成了动态选择,这就是多态
百度百科-验证
:初始化只有构造函数可以用
使用一个基类限制所有派生类接口形式(基类指针取出派生类对象)
#include <iostream>
using namespace std;
class shape{
public:
virtual double getC(void){
}
};
class Cir:public shape{
public:
Cir(double ri):r(ri) {}
double getC(void)
{
return 2*r*3.14;
}
int r;
};
class Tri:public shape{
public:
Tri(double a, double b, double c):e1(a), e2(b), e3(c){ }
double getC(void)
{
return e1 + e2 + e3;
}
private:
double e1;
double e2;
double e3;
};
class Rec: public shape{
public:
Rec(double e)
{
this->e = e;
}
double getC(void)
{
return 4*e;
}
private:
double e;
};
double countC(shape *arr[], int n)
{
double sum = 0;
for(int i = 0; i < n; i++)
{
sum += arr[i]->getC();
}
return sum;
}
int main()
{
Cir c(1);
Rec r(3);
Cir c1(2);
Tri t(3,3,3);
shape *arr[] = {&c, &r, &c1, &t};
cout << "total C:" << countC(arr, 4) << endl;
}
我们修改一下
编译不通过了,以为shape被我们写成了纯虚函数
#include <iostream>
using namespace std;
class shape{
public:
virtual double getC(void) = 0;
//{
//}
};
class Cir:public shape{
public:
Cir(double ri):r(ri) {}
double getC(void)
{
return 2*r*3.14;
}
int r;
};
class Tri:public shape{
public:
Tri(double a, double b, double c):e1(a), e2(b), e3(c){ }
double getC(void)
{
return e1 + e2 + e3;
}
private:
double e1;
double e2;
double e3;
};
class Rec: public shape{
public:
Rec(double e)
{
this->e = e;
}
double getC(void)
{
return 4*e;
}
private:
double e;
};
double countC(shape *arr[], int n)
{
double sum = 0;
for(int i = 0; i < n; i++)
{
sum += arr[i]->getC();
}
return sum;
}
int main()
{
shape x;
Cir c(1);
Rec r(3);
Cir c1(2);
Tri t(3,3,3);
shape *arr[] = {&c, &r, &c1, &t};
cout << "total C:" << countC(arr, 4) << endl;
}
#include <iostream>
using namespace std;
class A{
public:
A(){ }
virtual ~A(){ cout<<"A~~~~~~~~~"<<endl; }
virtual void show()
{
cout<<"AAAAAAAAAAAAA"<<endl;
}
};
class AX:public A{
public:
~AX(){ cout<<"AX~~~~~~~~~"<<endl; }
void show()
{
cout<<"BBBBBBBBBBBBB"<<endl;
}
};
int main()
{
AX a;
A b;
// AX *p = new AX;
// delete p;
//A *p = new AX;
//delete p;
/*
A a;
a.show();
AX b;
b.show();
*/
#if 0
AX a;
AX *q = &a;
A *p = &a;
q->show();
p->show();
#endif
}
创建了两个对象但是调用了三次析构函数,再派生时调用了一次基类的构造函数
如果对象是指针的话也是对的
AX *p = new AX;
delete p;
我们改动一下
A *p = new AX;
delete p;
居然没有任何问题。
这样是一个不安全的行为,当我们把基类的系公平析构函数也写成虚函数的样式,它又会变得安全。
class A{
public:
A(){ }
virtual ~A(){ cout<<"A~~~~~~~~~"<<endl; }
virtual void show()
{
cout<<"AAAAAAAAAAAAA"<<endl;
}
};
二、异常
#include <iostream>
#include <stdlib.h>
using namespace std;
int main()
{
int data = atoi("1234");
cout << data << endl;
}
#include <iostream>
#include <stdlib.h>
using namespace std;
int main()
{
int data = atoi("abcd");
cout << data << endl;
}
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
int myatoi(const char *str)
{
if(*str < '0' || *str > '9')
printf("wrong arg!!!\n");
else
return atoi(str);
}
int main()
{
// int data = atoi("abcd");
int data = myatoi("asdfas");
cout << data << endl;
}
依旧会把错误的值打印出来
像下面这样可以吗?
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
int myatoi(const char *str)
{
if(*str < '0' || *str > '9')
printf("wrong arg!!!\n");
goto xxx;
else
return atoi(str);
}
int main()
{
// int data = atoi("abcd");
int data = myatoi("asdfas");
cout << data << endl;
xxx:
cout << "xxxxxxxxxxxxxxxxxxx" << endl;
}
还是不行,因为C语言的goto是不能段外跳的C语言到现在都没有解决这个问题
但是C++给我们解决了
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
int myatoi(const char *str)
{
if(*str < '0' || *str > '9')
// printf("wrong arg!!!\n");
// goto xxx;
throw "wrong arg!!!";
else
return atoi(str);
}
int main()
{
// int data = atoi("abcd");
try{
int data = myatoi("asdfas");
cout << data << endl;
}
catch(const char *p)
{
cout << p << endl;
}
//xxx:
// cout << "xxxxxxxxxxxxxxxxxxx" << endl;
}
C++标准库里为我们提供了这样一个类
我们可以自己定义异常,下面定义一个感受感受
表达结果一样,但是这样更面向对象一点
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
class argexception:public exception{
public:
const char* what() const throw()
{
return "arg Err !";
}
};
int myatoi(const char *str)
{
if(*str < '0' || *str > '9')
throw argexception();
else
return atoi(str);
}
int main()
{
try{
int data = myatoi("asdfas");
cout << data << endl;
}
catch(argexception e)
{
cout << e.what() << endl;
}
}
三、转换函数
3.1标准转换函数
上面两个太危险了,现在已经废弃
#include <iostream>
using namespace std;
int main()
{
int a;
char *p = &a;
}
改成这样就过了
#include <iostream>
using namespace std;
int main()
{
int a;
char *p = (char*)&a;
}
下面是前两种方式
#include <iostream>
using namespace std;
int main()
{
#if 0
int a;
// char *p = (char*)&a;
char *p = reinterpret_cast<char *>( &a );
#endif
const int b = 100;
int *q = const_cast<int *>( &b );
}
#include <iostream>
using namespace std;
class A{
public:
virtual void show()
{
cout << "aaaaaaaaa" << endl;
}
};
class B:public A{
public:
void show()
{
cout << "bbbbbbbbbbb" << endl;
}
};
int main()
{
#if 0
int a;
// char *p = (char*)&a;
char *p = reinterpret_cast<char *>( &a );
#endif
#if 0
const int b = 100;
int *q = const_cast<int *>( &b );
#endif
#if 0
A a;
B &p = static_cast<B &>( a );
#endif
#if 1
try{
A a;
B &p = dynamic_cast<B &>( a );
}
catch(bad_cast e)
{
cout <<e.what()<<endl;
}
#endif
}
3.2自定义转换函数
#include <stdio.h>
#include <unistd.h>
#include <iostream>
using namespace std;
class Timer{
public:
Timer()
{
hour = 0;
min = 0;
sec = 0;
}
~Timer()
{
}
void addtimer(int sec=1)
{
this->min += (this->sec+sec)/60;
this->sec = (this->sec+sec)%60;
}
void show()
{
printf("%2d:%2d:%2d\n", hour, min, sec);
}
Timer operator+(int sec)
{
Timer tem;
tem.sec = this->sec+sec;
return tem;
}
Timer operator+(Timer &x)
{
Timer tem;
tem.sec = sec+x.sec;
tem.min = min+x.min;
tem.hour = hour+x.hour;
return tem;
}
Timer operator++(int)
{
Timer tem = *this;//backup
sec++;
return tem;
}
Timer operator++()
{
sec++;
return *this;
}
bool operator==(Timer &x)
{
if(sec==x.sec && min==x.min && hour==x.hour)
return true;
return false;
}
int &operator[](int i)
{
switch(i)
{
case 0:
return hour;
case 1:
return min;
case 2:
return sec;
}
}
operator int()
{
return sec + min * 60 + hour * 60 * 60;
}
friend ostream &operator<<(ostream &out, const Timer &t);
private:
int hour;
int min;
int sec;
};
ostream &operator<<(ostream &out, const Timer &t)
{
out << "hour: "<<t.hour << " min: "<<t.min<<" sec: "<<t.sec<< endl;
}
int main()
{
Timer t;
t.addtimer(3);
int sec = t;
cout << sec << endl;
}
3.3隐式转换(explicit)
#include <iostream>
using namespace std;
class mempool{
public:
mempool(int size)
{
data = new char[size];
cout << "cccccccccccccc" << endl;
}
~mempool()
{
delete [] data;
}
private:
char *data;
};
int main()
{
mempool a(100);
}
#include <iostream>
using namespace std;
class mempool{
public:
mempool(int size)
{
data = new char[size];
cout << "cccccccccccccc" << endl;
}
~mempool()
{
delete [] data;
}
private:
char *data;
};
int main()
{
// mempool a(100);
mempool a = 100;
}
结果是一样的,但是我们肯定不希望这样,我们不希望通过这种方式操作内存池。
#include <iostream>
using namespace std;
class mempool{
public:
explicit mempool(int size)
{
data = new char[size];
cout << "cccccccccccccc" << endl;
}
~mempool()
{
delete [] data;
}
private:
char *data;
};
int main()
{
// mempool a(100);
mempool a = 100;
}
封装Thread类
别人写的:
Thread类的封装_封装thread类_鬼才fjz的博客-CSDN博客
我修改一下:
#include "pthread.h"
#include <iostream>
using namespace std;
class Thread{
public:
Thread() : autoDelete_(false)
{
cout<<"Thread ..."<<endl;
}
virtual ~Thread()
{
cout<<"~Thread ..."<<endl;
}
void Start()
{
pthread_create(&threadId_, NULL, ThreadRoutine, this);
}
void Join()
{
pthread_join(threadId_, NULL);
}
private:
static void* ThreadRoutine(void* arg)
{
Thread* thread = static_cast<Thread*>(arg);
thread->Run();
if (thread->autoDelete_)
delete thread;
return NULL;
}
public:
void SetAutoDelete(bool autoDelete)
{
autoDelete_ = autoDelete;
}
private:
virtual void Run() = 0;
pthread_t threadId_;
bool autoDelete_;
};
int main()
{
}