07-C++ 异常

news2025/4/23 19:52:53

异常

1. 概念

  • 异常事件(如:除 0 溢出,数组下标越界,所要读取的文件不存在,空指针,内存不足等等)

  • 在C 语言对错误的处理是两种方法:

    • 一是使用整型的 返回值标识错误
    • 二是使用 errno 宏(可以简单的理解为一个全局整型变量)去记录错误。
  • c++异常 不可忽略 (如果忽略,进程结束)。

    • 异常作为一个类,可以拥有自己的成员,这些成员就可以传递足够的信息。
    • 抛出异常 ----> 捕获异常

示例:

int main(int argc, char *argv[])
{ 
    int num = 10 / 0;
    cout << "OVER" << endl;
    return 0;
} 
//不会显示OVER,程序异常结束

2. 抛出异常

语法:

throw 值或变量;  

例如:

throw 0;

throw 1.1;

throw 'a';

throw "abc";

3. 捕获异常

语法:

try{
    可能会产生异常的代码
    111
    222 出现异常
    333
} 
catch(数据类型1 变量名)
{
	当throw的值与数据类型1相同进入此处
} 
catch(数据类型2 变量名)
{
	当throw的值与数据类型2相同进入此处
} 
...
catch(...)
{
	当throw的值以上数据类型都不相同进入此处
}

4. 示例

#include <iostream>

using namespace std;

class A{

};
void my_error(int a, int b)
{
    if(b == 0)
    {
        //抛出异常
        //throw 0;
        //throw 1.2;
        //throw 'a';
        //throw "abc";
        throw new A();
    }
    cout << a / b << endl;
}
void fun01()
{
    try
    {
        my_error(10, 0);
    }
    catch(int e)
    {
        cout << "int抛出的异常值为:" << e << endl;
    }
    catch(double e)
    {
        cout << "double抛出的异常值为:" << e << endl;
    }
    catch(char e)
    {
        cout << "char抛出的异常值为:" << e << endl;
    }
    catch(...)
    {
        cout << "除以上类型外所有异常" << endl;
    }
}

int main(int argc, char *argv[])
{
    fun01();
    cout << "Hello World!" << endl;
    return 0;
}
//除以上类型外所有异常
//Hello World!

5. 栈解旋

概念:

  • 异常被抛出后,从进入 try 块起,到异常被抛掷前,这期间 在栈上构造的所有对象,都会被自动析构。

  • 析构的顺序与构造的顺序相反,这一过程称为栈的解旋 。

问题:在创建对象的过程中,抛出异常,此时 还 没来的及释放对象,所以会出现错误。

解决办法:用try…catch 捕获异常,就会自动释放内存空间

示例1:没有释放没存

#include <iostream>

using namespace std;
class B{
private:
    int x;
public:
    B(int x){
        this->x = x;
        cout << "B." << x << "被创建了" << endl;
    }
    ~B()
    {
        cout << "B." << x << "被销毁了" << endl;
    }
};
void fun02()
{
    B b1(1);
    B b2(2);
    B b3(3);
    //抛出异常
    throw 0;
}

int main(int argc, char *argv[])
{
    fun02();
    cout << "Hello World!" << endl;
    return 0;
}

在这里插入图片描述

示例2:使用try…catch后,自动释放内存

#include <iostream>

using namespace std;
class B{
private:
    int x;
public:
    B(int x){
        this->x = x;
        cout << "B." << x << "被创建了" << endl;
    }
    ~B()
    {
        cout << "B." << x << "被销毁了" << endl;
    }

};
void fun02()
{
    B b1(1);
    B b2(2);
    B b3(3);
    //抛出异常
    throw 0;
}

int main(int argc, char *argv[])
{
    try
    {
        fun02();
    }
    catch(int e)
    {
        
    }

    cout << "Hello World!" << endl;
    return 0;
}

在这里插入图片描述

6. 异常的接口声明

作用:限定异常抛出的类型

语法:

返回值类型 函数名(形参列表)throw(数据类型1,数据类型2,...)
{
	函数体
} 

注意:

  • 声明异常后,当前函数中只能抛出指定类型的异常
  • throw() 括号中啥也不写,表示不允许抛出任何异常

示例:

#include <iostream>

using namespace std;

class A{

};

void my_error(int a, int b)
{
    if(b == 0)
    {
        //抛出异常
        //throw 0;
        //throw 1.2;
        //throw 'a';
        //throw "abc";
        throw new A();
    }
    cout << a / b << endl;
}
void fun01()
{
    try
    {
        my_error(10, 0);
    }
    catch(int e)
    {
        cout << "int抛出的异常值为:" << e << endl;
    }
    catch(double e)
    {
        cout << "double抛出的异常值为:" << e << endl;
    }
    catch(char e)
    {
        cout << "char抛出的异常值为:" << e << endl;
    }
    catch(...)
    {
        cout << "除以上类型外所有异常" << endl;
    }
}

class B{
private:
    int x;
public:
    B(int x){
        this->x = x;
        cout << "B." << x << "被创建了" << endl;
    }
    ~B()
    {
        cout << "B." << x << "被销毁了" << endl;
    }

};
void fun02()
{
    B b1(1);
    B b2(2);
    B b3(3);
    //抛出异常
    throw 0;
}
//当前函数只能抛出int或char类型的异常
//void fun03() throw(int,char)
//throw() 说明当前函数不会抛出任何异常
void fun03() throw()
{
    throw 0;
}
int main(int argc, char *argv[])
{
//    try
//    {
//        fun03();
//    }
//    catch(int e)
//    {
//    }
    fun03();
    cout << "Hello World!" << endl;
    return 0;
}
// 此时会报错
//terminate called after throwing an instance of 'int'
//抛出'int'实例后调用终止

7. 异常对象的生命周期

  • 抛出异常对象
    • 多次 调用对象的构造和析构
  • 抛出异常对象指针
    • 只调用 构造函数,没有析构
  • 抛出异常对象引用 (推荐使用)
    • 只会调用一次构造,一次析构
    • 注意:隐式创建对象,不然会触发拷贝构造

7.1 示例1:抛出异常对象

#include <iostream>

using namespace std;
class MyError
{
public:
    MyError(){
        cout << "构造函数" << endl;
    }
    MyError(const MyError& e){
        cout << "拷贝构造" << endl;
    }
    ~MyError(){
        cout << "析构函数" << endl;
    }
};

void test01()throw(MyError)
{
    throw MyError(); //调用构造 
}
void fun01()
{
    try{
        test01();
    }
    catch(MyError e) //调用拷贝构造
    {

    }
}

int main(int argc, char *argv[])
{
    fun01();
    return 0;
}
//构造函数
//拷贝构造
//析构函数
//析构函数

注意:显示创建对象 会调用 构造和拷贝构造

7.2 示例2:抛出异常对象指针

#include <iostream>

using namespace std;
class MyError
{
public:
    MyError(){
        cout << "构造函数" << endl;
    }
    MyError(const MyError& e){
        cout << "拷贝构造" << endl;
    }
    ~MyError(){
        cout << "析构函数" << endl;
    }
};

void test02()
{
    //new 返回的是error对象的指针
    throw new MyError();
}

void fun02()
{
    try{
        test02();
    }
    catch(MyError *e)
    {

    }
}

int main(int argc, char *argv[])
{
    fun02();
    return 0;
}
//构造函数

7.3 示例3:抛出异常对象引用 (推荐使用)

#include <iostream>

using namespace std;
class MyError
{
public:
    MyError(){
        cout << "构造函数" << endl;
    }
    MyError(const MyError& e){
        cout << "拷贝构造" << endl;
    }
    ~MyError(){
        cout << "析构函数" << endl;
    }
};

void test03()
{
    throw MyError();
}

void fun03()
{
    try{
        test03();
    }
    catch(MyError& e)
    {

    }
}
int main(int argc, char *argv[])
{
    fun03();
    return 0;
}
//构造函数
//析构函数

8. 异常的多态

概念:子类异常对象 可以被 父类异常类型捕获 ,原理是上行,子传父,多态。

示例1:

#include <iostream>

using namespace std;

class BaseException{};
class MyException01:public BaseException{};
class MyException02:public BaseException{};
void test05()
{
    try{
        throw MyException01();
    }
    catch(BaseException)
    {
        cout << "可以捕获子类异常" << endl;
    }
}
int main(int argc, char *argv[])
{
    test05();
    return 0;
}
//可以捕获子类异常

示例2:重写父类虚函数

#include <iostream>

using namespace std;
class BaseException{
public:
    virtual void printMsg(){}
};
class NullException:public BaseException{
public:
    void printMsg(){
        cout << "空指针异常" << endl;
    }
};
class ArrOutException:public BaseException{
public:
    void printMsg(){
        cout << "数组下标越界异常" << endl;
    }
};
void test05()
{
    try{
        throw NullException();
    }
    catch(BaseException &e)
    {
        e.printMsg();
    }
}
int main(int argc, char *argv[])
{
    test05();
    return 0;
}
//空指针异常

9. 标准异常库

9.1 简介

标准库中也提供了很多的 异常类,它们是通过类 继承组织起来 的。

异常类继承层级结构图所示 :

在这里插入图片描述

标准异常类的成员:

① 在上述继承体系中,每个类都有提供了构造函数、复制构造函数、和赋值操作符重载。

② logicerror 类及其子类、 runtimeerror 类及其子类,它们的构造函数是接受一个string 类型的形式参数,用于异常信息的描述

③ 所有的异常类都有一个 what()方法,返回 const char* 类型(C 风格字符串)的值,描述异常信息。

标准异常类的具体描述:

异常名称描述
exception所有标准异常类的父类
bad_alloc当 operator new and operator new[],请求分配内存失败时
bad_exception这是个特殊的异常,如果函数的异常抛出列表里声明了 badexception 异常,当函数内部抛出了异常抛出列表中没有的异 常,这是调用的 unexpected 函数中若抛出异常,不论什么类 型,都会被替换为 badexception 类型
bad_typeid使用 typeid 操作符,操作一个 NULL 指针,而该指针是带有虚函数的类,这时抛出 bad_typeid 异常
bad_cast使用 dynamic_cast 转换引用失败的时候
ios_base::failureio 操作过程出现错误
logic_error逻辑错误,可以在运行前检测的错误
runtime_error运行时错误,仅在运行时才可以检测的错误

logic_error 的子类:

异常名称描述
length_error试图生成一个超出该类型最大长度的对象时,例如 vector 的 resize 操作
domain_error参数的值域错误,主要用在数学函数中。例如使用一个负值调 用只能操作非负数的函数
outofrange超出有效范围
invalid_argument参数不合适。在标准库中,当利用 string 对象构造 bitset 时, 而 string 中的字符不是’0’或’1’的时候,抛出该异常

runtime_error 的子类:

异常名称描述
range_error计算结果超出了有意义的值域范围
overflow_error算术计算上溢
underflow_error算术计算下溢
invalid_argument参数不合适。在标准库中,当利用 string 对象构造 bitset 时, 而 string 中的字符不是’0’或’1’的时候,抛出该异常

9.2 标准异常使用

示例:

#include <iostream>

using namespace std;
void test02()
{
    //throw runtime_error("使用系统提供的运行时异常类");
     throw logic_error("逻辑错误");
}

void fun02()
{
    try{
        test02();
    }
//    catch(runtime_error &e)
//    {
//        const char * msg = e.what();
//        cout << msg << endl;
//    }
    catch(exception &e)
    {
        const char * msg = e.what();
        cout << msg << endl;
    }
}

int main(int argc, char *argv[])
{
    fun02();
    cout << "Hello World!" << endl;
    return 0;
}
//逻辑错误

10. 自定义异常

步骤:

  1. 定义一个类
  2. 继承与异常类
  3. 重写wait方法
方式1: 继承总异常类 exception 需要冲写what() 函数
方式2: 继承总异常类Exception下的某一个 异常类,此处是 runtime_error

示例:

#include <iostream>
using namespace std;
//方式1: 继承总异常类 exception 需要冲写what() 函数
class my_error:public exception{
private:
    //记录异常信息
    char *msg;
public:
    my_error(char *msg){
        this->msg = msg;
    }
    //重写父类 what() 函数
    const char* what() const _GLIBCXX_USE_NOEXCEPT
    {
        return msg;
    }
};

//方式2: 继承总异常类Exception下的某一个 异常类,此处是 runtime_error
class my_error02:public runtime_error{
public:
    my_error02(char *msg):runtime_error(msg){}
};
//调用方式1
void test()
{
    throw my_error("自定义异常");
}
//调用方式2
void test02()
{
    throw my_error02("自定义异常2");
}
void fun01()
{
    try{
        test02();
    }
    catch(exception &e)
    {
        cout << e.what() << endl;
    }
}

int main(int argc, char *argv[])
{
    fun01();
    return 0;
}
//自定义异常2

11. 练习总结

11.1 示例1

#include <iostream>
#include <cstdio>
using namespace std;

void test03(int a,int b)
{
    if(b == 0)
    {
        throw "除数不能为0";
    }
    cout << a / b << endl;
}

void test04()
{
    FILE* f = fopen("xxx","r");
    if(f == NULL)
    {
        throw "文件路径不正确";
    }
}

void fun03()
{
    try{
        test03(10,0);
    }
    catch(char const* e)
    {
        cout << e << endl;
    }
}
void fun04()
{
    try{
        test04();
    }
    catch(char const* e)
    {
        cout << e << endl;
    }
}
int main(int argc, char *argv[])
{
    fun03();
    fun04();
    return 0;
}
//除数不能为0
//文件路径不正确

11.2 示例2:ArrayList

arraylisat.hpp

#include <cstring>
template<class X>
class ArrayList{
    X *data;
    int size;
    int count;
public:
    ArrayList();
    ~ArrayList();
    void add(X& x);
    X& get(int index);
    int getSize();
};


template<class X>
ArrayList<X>::ArrayList()
{
    data = new X[2];
    count = 2;
    size = 0;
}

template<class X>
ArrayList<X>::~ArrayList()
{
    delete [] data;
}

template<class X>
void ArrayList<X>::add(X& x)
{
    if(size == count)
    {
        count *= 2;
        X* newData = new X[count];
        memcpy(newData,data,size*sizeof(X));
        delete [] data;
        data = newData;
    }
    data[size] = x;
    size++;
}

template<class X>
X& ArrayList<X>::get(int index)
{
    //判断传入的参数是否合规,应该 >0,<size;
    //否则抛出异常 0
    if(index < 0 || index >= size)
    {
        throw 0;
    }
    return data[index];
}

template<class X>
int ArrayList<X>::getSize()
{
    return size;
}

main.cpp

#include <iostream>
#include "arraylist.hpp"

using namespace std;

class A{
    int num;
public:
    A(){}
    A(int num):num(num){}
    void print()
    {
        cout << num << endl;
    }
};
int main(int argc, char *argv[])
{

    ArrayList<A> list;
    A d01 = 1;
    A d02 = 2;
    A d03 = 3;
    A d04 = 4;
    A d05 = 5;
    list.add(d01);
    list.add(d02);
    list.add(d03);
    list.add(d04);
    list.add(d05);
    //捕获异常,此时ArrayList中只有5个数据,参数10>size
    try{
        A& a = list.get(10);
        a.print();
    }
    catch(int e)
    {
        cout << "有bug" << endl;
    }

    return 0;
}
//有bug

11.3 示例3:读取文件

① myutils.h

#ifndef MYFILE_UTILS_H
#define MYFILE_UTILS_H

//声明读取文件函数
extern char *get_file_text(char *filepath);
#endif // MYFILE_UTILS_H

② filepath_error.h

#ifndef FILEPATH_ERROR_H
#define FILEPATH_ERROR_H
#include <iostream>
//定义路径错误函数,继承runtime_error
#include <iostream>
using namespace std;
class filepath_error:public runtime_error
{
public:
    filepath_error();
};
#endif // FILEPATH_ERROR_H

③ filepath_error.cpp

#include "filepath_error.h"

filepath_error::filepath_error():runtime_error("文件路径有误")
{

}

④ myutils.cpp

#include <iostream>
#include <cstdio>
#include <cstring>
#include "myfileutils.h"
#include "filepath_error.h"

//根据文件名读取文件中的内容
char *get_file_text(char *filepath)
{
    FILE *f = fopen(filepath, "r");
    if(f == NULL)
    {
        //throw 0;
        throw filepath_error();
    }

    //计算文本长度
    fseek(f, 0, 2);
    int len = ftell(f);
    //创建存放读取的文件的数组
    char *c = new char[len];
    //将数组数据置零
    memset(c, 0, len);
    //游标恢复置开始
    fseek(f, 0, 0);
    //读取数据
    fread(c, len, 1, f);
    fclose(f);
    return c;

}
//甲乙丙丁戊己庚辛壬癸
//子丑寅卯陈思武威申酉戌亥

⑤ main.cpp

#include <iostream>
#include "myfileutils.h"
#include "filepath_error.h"

using namespace std;

int main(int argc, char *argv[])
{
    try
    {
        //char *content = get_file_text("D:/io");
        char *content = get_file_text("D:/a.txt");
        cout << content << endl;
    }
    catch(exception &e)
    {
        cout << e.what() << endl; //文件路径有误
    }

    return 0;
}

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

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

相关文章

自创题目——贴对联

预估难度 简单 题目描述 小明家最近要挂对联&#xff0c;小明要知道对联怎么挂&#xff0c;以及对联合不合规。如果不合规&#xff0c;输出"扔了吧"&#xff0c;否则输出&#xff1a; 横批 ... ... 输入格式 共三行&#xff1b; 第一行&#xf…

MySQL入门教程-函数,索引

4MySQL函数 常用函数 -- 数学运算SELECT ABS(-8); -- 绝对值SELECT CEIL(5.1); -- 向上取整SELECT CEILING(5.1); -- 向上取整SELECT RAND(); -- 返回0~1之间的一个随机数SELECT SIGN(-10); -- 返回一个数的符号;0返回0;正数返回1;负数返回-1​-- 字符串函数SELECT CHAR_LENGT…

树低级(C语言版)

一.树基本计算规则 关于树的大部分知识点我们都讲过了&#xff0c;那么如果我给你树的节点&#xff0c;你可以算出叶子节点个数吗&#xff1f; 下面我们总结下一些计算规则&#xff1a; 1.父子计算规则&#xff1a; parent(child-1)/2; leftchildparent*21,rightchildpare…

swing快速入门(三十三)确认对话框

注释很详细&#xff0c;直接上代码 新增内容 1.确定对话框返回值对应值 2.为文本域增加滚动条 package swing31_40;import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent;public class swing_test_31 {// 创建一个JFrameJFrame jFrame new JFrame(…

《现代操作系统》第十二章习题答案

计算机硬件的改进主要归功于更小的晶体管。一些限制因素包括&#xff1a;(a) 光的波动性可能限制传统光刻技术制造集成电路的能力&#xff0c;(b) 固体中个别原子的迁移性可能导致非常薄的半导体、绝缘体和导体层的性能退化&#xff0c;(c) 背景辐射活性可能破坏分子键或影响非…

pytorch01:概念、张量操作、线性回归与逻辑回归

目录 一、pytorch介绍1.1pytorch简介1.2发展历史1.3pytorch优点 二、张量简介与创建2.1什么是张量&#xff1f;2.2Tensor与Variable2.3张量的创建2.3.1 直接创建torch.tensor()2.3.2 从numpy创建tensor 2.4根据数值创建2.4.1 torch.zeros()2.4.2 torch.zeros_like()2.4.3 torch…

回顾 2023,展望 2024

by zhengkai.blog.csdn.net 项目与心得 今年最大的项目和心得&#xff0c;非GCP莫属&#xff0c;作为全球顶尖的云平台&#xff0c; GCP有他的优势&#xff0c;也有很多难用的地方。但是作为当时的一个strategic solution&#xff0c;我们的印度本地化项目必须使用GCP&#xf…

Linux权限的基本理解

一:&#x1f6a9;Linux中的用户 1.1&#x1f966;用户的分类 &#x1f31f;在Linux中用户可以被分为两种用户: 超级用户(root):可以在Linux系统中做各种事情而不被约束普通用户:只能做有限的事情被权限约束 在实际操作时超级用户的命令提示符为#,普通用户的命令提示符为$,可…

数模混合SoC芯片中LEF2Milkyway的golden flow

在数模混合芯片中的项目中&#xff0c;特别是数字模块很少甚至只有一个简单的数字控制逻辑时&#xff0c;我们要做数字模块的后端实现时&#xff0c;通常模拟那边会问我们实现需要他们提供哪些数据。 通常来说&#xff0c;我们可以让模拟设计提供数字模块的GDS或LEF文件即可。…

nodejs+vue+微信小程序+python+PHP特困救助供养信息管理系统-计算机毕业设计推荐

通过走访某特困救助供养机构实际情况&#xff0c;整理特困救助供养机构管理的业务流程&#xff0c;分析当前特困救助供养机构管理存在的各种问题&#xff0c;利用软件开发思想对特困救助供养机构特困救助供养机构管理进行系统设计分析。通过服务端程序框架进行设计&#xff0c;…

网际协议IPv4

基本介绍 网际协议IP是TCP/IP体系中两个重要的协议之一。IPv4虽有最终被IPv6取代的趋势&#xff0c;但它仍是当前使用的最重要的因特网协议。 与IP配套使用的还有3个协议&#xff1a; 地址解析协议ARP(Address Resolution Protocol)因特网控制报文协议ICMP(Internet Control …

Docker 入门 ------容器互通以及Dockerfile

1. 端口映射以及容器互联 Docker 除了通过网络访问&#xff0c;还提供了两种很方便的功能来满足服务访问的基本需求&#xff1a; 允许映射容器内应用的服务端口到本地宿主主机互联机制实现多个容器间通过容器名来快速访问 1.1 容器映射实现访问容器 1.1.1 从外部访问容器应…

中间人攻击是什么,会产生哪些危害,如何有效防止中间人攻击

简介 中间人攻击&#xff08;Man-in-the-Middle Attack&#xff0c;简称MITM攻击&#xff09;是一种网络攻击&#xff0c;其原理是攻击者通过各种技术手段将受攻击者控制的一台计算机虚拟放置在网络连接中的两台通信计算机之间&#xff0c;这台计算机称为“中间人”。在攻击过…

【滑动窗口】C++算法:可见点的最大数目

作者推荐 动态规划 多源路径 字典树 LeetCode2977:转换字符串的最小成本 本题涉及知识点 滑动窗口 LeetCode 1610可见点的最大数目 给你一个点数组 points 和一个表示角度的整数 angle &#xff0c;你的位置是 location &#xff0c;其中 location [posx, posy] 且 point…

Linux文件系统结构及相关命令1(man pwd ls ctrl +Shift +T ls /etc)

Linux的文件系统结构 某所大学的学生可能在一两万人左右&#xff0c;通常将学生分配在以学院-系班为单位的分层组织机构中。 如何查找一名学生&#xff1f; 最笨的办法&#xff1a;依次问询大学中的每一个学生&#xff0c;直到找到为止。 查询效率高的方法&#xff1a;按照从…

2023年新一代开发者工具 Vue ,正式开源!

以下文章来源于前端充电宝 &#xff0c;作者CUGGZ 近日&#xff0c;Vue 新一代开发者工具&#xff08;DevTools&#xff09;正式开源&#xff01;Vue DevTools 是一个旨在增强 Vue 开发人员体验的工具&#xff0c;它提供了一些功能来帮助开发者更好地了解 Vue 应用。下面就来看…

用IDEA创建/同步到gitee(码云)远程仓库(保姆级详细)

前言&#xff1a; 笔者最近在学习java&#xff0c;最开始在用很笨的方法&#xff1a;先克隆远程仓库到本地&#xff0c;再把自己练习的代码从本地仓库上传到远程仓库&#xff0c;很是繁琐。后发现可以IDEA只需要做些操作可以直接把代码上传到远程仓库&#xff0c;也在网上搜了些…

【FileZilla】的基本使用

一、FileZilla的使用 1.1 FileZilla简介 1.2 软件下载 到官方网站下载 FileZilla 的服务端和客户端程序 FileZilla - The free FTP solution 自行下载即可 1.3 软件安装 &#xff08;1&#xff09;先安装服务端【傻瓜式安装】&#xff0c;一直下一步下一步安装即可 &#xf…

Python绘制高级图表(1):绘制条形统计图

一、初始化 1. 引入库&#xff0c;设置画笔 from turtle import * t Turtle() t.color("black") t.width(3)2. 为了美观&#xff0c;画出xy轴 (1) 普通型 from turtle import * t Turtle() t.color("black") t.width(3)# 以画布为600 * 600为例 # 1.…

搭建maven私服

maven maven简介 什么是maven&#xff1f; Maven这个单词来自于意第绪语&#xff08;犹太语&#xff09;&#xff0c;意为知识的积累。 Maven项目对象模型(POM)&#xff0c;可以通过一小段描述信息来管理项目的构建&#xff0c;报告和文档的项目管理工具软件。 Maven 除了以…