C++——多态、异常、转化函数

news2024/11/15 4:40:42

目录

一、多态

二、异常

​三、转换函数

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

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/171439.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vite+vue3环境变量的配置

文章目录一、vite1. 环境变量2. env 文件2.1 环境加载优先级2.2 TypeScript 的智能提示3. 模式二、vue1. 开发环境2. 生产环境3. 在 vite.config.ts 使用环境变量一、vite vite官方文档&#xff1a;环境变量和模式 1. 环境变量 Vite 在一个特殊的 import.meta.env 对象上暴露…

爱普生LQ-635K针式打印机打链式打印纸设置自动切纸方法

链式打印纸还有别的叫法&#xff0c;折叠式打印纸、复写打印纸、等分打印纸、电脑打印纸...... 其实链式打印纸是打印纸的两边带孔的具有复写功能的一种。链式打印纸可连续打印&#xff0c;很合适大量的使用&#xff0c;节约放纸时间。 链式打印纸有整张、二等分、三等分的规格…

python比较两张图片并获取精准度

先安装依赖库dlib、face_recognition、cv2下载wheel文件&#xff1a;python3.6&#xff1a;dlib-19.7.0-cp36-cp36m-win_amd64.whl: https://drfs.ctcontents.com/file/1445568/768652503/68cb5d/Python/dlib-19.7.0-cp36-cp36m-win_amd64.whlpython3.7:dlib-19.17.99-cp37-cp3…

Spring中的IOC和AOP

IOC(控制反转)和AOP(面向方面编程)作为Spring框架的两个核心&#xff0c;很好地实现了解耦合。所以&#xff0c;简单来说&#xff0c;Spring是一个轻量级的控制反转&#xff08;IoC&#xff09;和面向切面&#xff08;AOP&#xff09;的容器框架。 spring的基本框架主要包含六…

2023年中职网络安全技能竞赛网页渗透(审计版)

三、竞赛任务书内容 (一)拓扑图 网页渗透测试 任务环境说明: 服务器场景:Server2127服务器场景操作系统:未知(封闭靶机)用户名:未知 密码:未知访问服务器网站目录1,根据页面信息完成条件,将获取到的flag提交;访问服务器网站目录2,根据页面信息完成条件,将获取…

SpringCloud(10):Hystrix请求缓存

1 类继承的方法来实现请求缓存 1.1 编写CacheCommand类 package com.study.service.hystrix;import com.netflix.hystrix.HystrixCommand; import com.netflix.hystrix.HystrixCommandGroupKey; import com.netflix.hystrix.HystrixCommandKey; import com.netflix.hystrix.H…

面试 | Python 自动化测试技术面试真题

本文为面试某公司测试开发&#xff0f;自动化测试工程师时的面试题笔记。 全部笔试内容没有全部写全&#xff0c;只贴通用性的技术相关的笔试面试题&#xff0c;至于测试理论和团队管理的问题&#xff0c;都是大同小异&#xff0c;也没什么实际的参考价值。 1.直接手写一个 Pyt…

智慧工地 | 数字孪生楼宇施工管理平台

随着科学技术的进步&#xff0c;时代的发展&#xff0c;越来越多的智慧应用走进我们身边&#xff0c;万物互联不再是口号。当前智慧城市建设的兴起&#xff0c;都在要求建筑实现与物联网结合&#xff0c;使其扩展和延伸到建筑物和任何物品之间进行交换和通信&#xff0c;也就是…

python环境构造

目录 1. python安装包下载 2. 双击默认安装即可 3. python插件安装 4. 本地手动安装python插件 1. python安装包下载 可以去官网 (Download Python | Python.org) 下载&#xff0c;但是可能速度会比较慢 也可以去我的百度网盘下载&#xff0c;版本是win64 3.11.1版&#xf…

机器视觉 · 工业光源

文章目录光源 环形光源光源 环形漫反射光源光源 高亮环形无影光源光源 高亮环形大功率光源光源 双向高均匀漫射环形光源光源 多方向高均匀漫射环形光源光源 球状分布式对称无影光源光源 条形光源光源 条形光源光源 高亮条形光源光源 条形组合光源光源 背光源光源 …

安卓包在真机上安装时的“风险提示”问题

1&#xff09;安卓包在真机上安装时的“风险提示”问题 ​2&#xff09;iOS下AssetBundle的加载疑问 3&#xff09;特效用粒子系统&#xff0c;模拟器里出现花屏问题 4&#xff09;IL2CPP编译的Protobuf&#xff0c;反射类运行时报空 这是第321篇UWA技术知识分享的推送&#xf…

抖音商品机会潜力分析报告竞赛-3等奖作品分析

文章目录数据集介绍需要1以及结论需求2以及结论推荐开发商品A&#xff1a;鹊牌 三合一爆米花球形焦糖味奶香味100g玉米50g糖 50克油 包邮推荐开发商品B&#xff1a;【云南松茸菌汤包】熬汤必备 正宗云南产地货 60g/袋 包邮推荐开发商品C&#xff1a;推荐_【三只松鼠_巨型零食大…

力扣 1807. 替换字符串中的括号内容

题目 给你一个字符串 s &#xff0c;它包含一些括号对&#xff0c;每个括号中包含一个 非空 的键。 比方说&#xff0c;字符串 “(name)is(age)yearsold” 中&#xff0c;有 两个 括号对&#xff0c;分别包含键 “name” 和 “age” 。 你知道许多键对应的值&#xff0c;这些…

年度盘点(四)丨2022计讯物联企业文化活动精彩盘点

2022年&#xff0c;计讯物联聚焦企业文化软实力&#xff0c;以文化力引领企业发展力和核心竞争力&#xff0c;以塑造一流队伍为核心&#xff0c;不断找准发力点&#xff0c;深度策划系列企业文化活动&#xff0c;不断促进企业文化与公司业务的融合&#xff0c;持续增强全体计讯…

「自控原理」3.3 稳定性与稳态误差、时域校正

本节介绍稳定性分析的原理以及代数稳定性判据&#xff08;劳斯判据&#xff09; 本节介绍系统稳态误差的定义及计算方法 本节介绍时域校正方法 文章目录稳定性分析稳定的充要条件与必要条件劳斯判据-Routh例题两种特殊情况问题辨析稳态误差误差与稳态误差的定义计算稳态误差的一…

【手写 Vue2.x 源码】第三十篇 - diff算法-比对优化(上)

一&#xff0c;前言 上篇&#xff0c;介绍了diff算法-节点比对&#xff0c;主要涉及以下几点&#xff1a; 介绍了 diff 算法、对比方式、节点复用实现了外层节点的 diff 算法不同节点如何做替换更新相同节点如何做复用更新&#xff1a;文本、元素、样式处理 本篇&#xff0c…

在线教育-谷粒学院学习笔记(五)

文章目录1 内容介绍2 课程分类前端实现3 课程列表功能实现4 课程管理概括5 添加课程信息后端实现6 添加课程信息前端实现7 前端完善1 内容介绍 添加课程分类前端实现课程分类列表显示功能&#xff08;树形结构&#xff09;课程管理模块需求添加课程基本信息功能 2 课程分类前…

如何设置OpenFeign请求超时

Feign和OpenFeign介绍 Feign集成了Ribbon、RestTemplate实现了负载均衡的执行Http调用&#xff0c;只不过对原有的方式&#xff08;RibbonRestTemplate&#xff09;进行了封装&#xff0c;开发者不必手动使用RestTemplate调服务&#xff0c;而是定义一个接口&#xff0c;在这个…

byzer笔记本使用

byzer笔记本使用 数据源的定义 对于etl&#xff0c;起始的第一步往往是定义一个数据来源。 设置数据源 通过设置 -> 外部数据源 -> 新增可以新增jdbc类型的数据源。 命令指定数据源 notebook中可以使用connect命令进行jdbc数据源的指定: > SET user"root&q…

Elasticsearch(四)--一文弄懂ES的映射操作

一、前言 上一章学习了ES的索引相关操作&#xff0c;那么这一章就轮到映射&#xff0c;了解映射操作最重要的点就是去学习ES的数据类型。那么本章我们会了解到映射的创建、查看和修改操作&#xff0c;然后详细介绍ES中的基本数据类型和复杂的数据类型&#xff0c;并且会对常用…