当前位置: 首页 > news >正文

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()
{

}

相关文章:

  • wordpress群发/长沙seo优化首选
  • 网站开发语言数据库有几种/旅游新闻热点
  • 洛阳西工区做网站哪家好/公司网站建设推广
  • 和淘宝同时做电商的网站/小吴seo博客
  • 建设行政主管部门官方网站/下载百度2023最新版安装
  • 上海静安网站建设/资源企业网站排名优化价格
  • 数据结构 - 学习笔记 - 红黑树前传——234树
  • 裸机与RTOS到FreeRTOS基础 | FreeRTOS一
  • 深度学习24-多智能体强化学习
  • leetcode354. 俄罗斯套娃信封问题
  • 【批处理脚本】-1.1-注释命令rem
  • 【MySQL进阶】MySQL事务隔离与锁机制底层原理万字总结(建议收藏!!)
  • Qt使用第三方库QXlsx将数据库的数据导出为Excel表格
  • DevOps利器之二(Git,Gitlab)
  • aws imagebuilder 理解并使用imagebuilder构建pcluster自定义ami
  • 关于ElasticSearch的那些事,面试常见问题
  • 浅析正则表达式+范围规则校验表达式+js从字符串中截取数字
  • 设计模式——代理模式