尽管抽象类和接口有着相似之处,但也有明显的区别。下面将详细介绍这两个概念的不同点。 1、抽象类 抽象类是指不能直接实例化的类,只能被用来派生其他类,它被设计成为仅包含可继承的方法、属性和变量。...抽象类通常用于在类层次结构的根部建立一个适当的上下文语境。常见的抽象类特征如下: 抽象类可以包含成员变量和成员方法,也可以包含抽象方法以及非抽象方法。...2、接口 接口和抽象类一样也是一种特殊类型的类,它仅声明了一组或者多组方法以及常量,可以被看作是一个对外公开的 API 契约。接口在 Java 中属于比抽象类更加抽象的概念。...在接口中声明方法时必须使用关键字 public 或者 default 修饰,并且通常不需要使用 abstract 关键词,因为接口中所有方法都默认为抽象方法。...3、抽象类和接口的区别 抽象类和接口都可以理解为一种模板或契约,它们之间虽然有相似点,但也存在很多不同之处。
ref是传递参数的地址,out是返回值,两者有一定的相同之处,不过也有不同点。 使用ref前必须对变量赋值,out不用。 ...out的函数会清空变量,即使变量已经赋值也不行,退出函数时所有out引用的变量都要赋值,ref引用的可以修改,也可以不修改。 ...,必须对x和y赋值,否则会报错。 ...//y = x; //上面这行会报错,因为使用了out后,x和y都清空了,需要重新赋值,即使调用函数前赋过值也不行 x = 1; y = 2; } static void refTest... //out使用前,变量可以不赋值 outTest(out a, out b); Console.WriteLine("a={0};b={1}",a,b); int c=11,d=22;
在Bash编程中,set -e(或更正式地写作set -o errexit)和使用trap命令来捕获EXIT或ERR信号有相似的目的,即在脚本中检测错误并作出相应处理,但它们在行为和使用场景上有一些不同点...不同点 控制粒度: set -e提供的是全局性的错误处理机制,一旦任何命令失败,整个脚本立即终止。这可能导致在某些情况下过于严格,比如在预期某些命令可能会失败但希望后续命令继续执行的场景。...你可以定义自己的错误处理函数来决定脚本应该如何响应特定类型的错误,比如记录错误信息、清理资源或有选择性地继续执行。 适用范围: set -e影响整个脚本,包括直接执行的命令和子shell。...行为细节: set -e有一些例外情况不会导致脚本退出,比如在某些复合命令内部的失败,或者是失败命令出现在&&、||、if、while、until结构中。...需要注意的是:在“进程替换”(process substitution)中执行的 exit 命令或因错误触发的陷阱,并不会终止外部进程,只会结束那个特定的子进程。
不是预期的 “abc cba” 和 “efg gfe” 2. nextLine 使用举例: 输入 1: 2 abc cba 结果 1: str[0] = “” str[1] = “abc” 原因:以回车...回车符 “\r” 它被丢弃在缓冲区中,现在缓冲区中,只有一个 \r ,于是 下一次 nextLine 扫描的时候就又扫描到了 \r,返回它之前的内容,也是啥都没有 “” ,然后再把 \r 去掉, 对于...这个扫描器在扫描过程中判断停止的依据就是“结束符”,空格,回车,tab 都算做是结束符 而坑点在于 next 系列的,也就是下面这些函数:next nextInt nextDouble nextFloat...这些函数与 nextLine 连用都会有坑 坑点就是 next 系列的函数返回了数据后,会把回车符留在缓冲区,因此我们下一次使用 nextLine 的时候会碰到读取空字符串的情况 解决方案:输入都用...nextLine ,做格式转换 输入 next 系列函数调用后,中间调用一次 nextLine 调用去掉了回车符后,再调用一次 nextLine 调用真正输入我们的数据 都使用 nextLine: class
一、类模板示例 - 数组类模板 1、需求分析 类模板 的 作用就是 令 算法 和 数据类型分离 ; 本篇博客中 开始 使用 类模板 开发一个 数组类 , 数组 中 可以维护 不同类型的 元素数据 , 如...声明与实现 在声明类时 , 前面加上 模板类型声明 template , 说明在类中要使用类型 T ; 在 Array 类中 , 声明 构造函数 , 拷贝构造函数 , 析构函数...析构函数 : 在 类模板 外部 访问 类模板 中声明的 函数 , 先显示声明 模板类型 template , 然后在下面使用 域作用符 访问 类模板中的 函数 , 域作用符...前面的 类型 , 需要 注明实际类型 , 这里使用 Array:: 访问类模板 中的 函数 ; 注意 : 如果在 函数参数 和 函数返回值 中 , 使用到了 Array 类型 , 那么也必须加上...实际类型 , 否则编译时会报错 ; 在 函数体 中使用到了 Array 类型 , 可以不加 实际类型 ; 构造函数 和 拷贝构造函数 中 , 创建 T 类型的数组 , 使用 m_space
,在我写这个系统之前,我在图书馆的借书页面,看了将近两个小时,中途又看了好多次,这次代码不能说是一个完美可以当作工程性的使用,其中还有很多测试环节,还有部分功能没有实现,比如二次检索,三次检索功能,数据少得可怜...时间类第一次调试运行,测试有参无参,重载>和+ ? 写到后边发现,自己重载的+错了,而且还需要计算两个时间类相差的时间,回头从新写的重载+,跟- 图书类 ?...转而写get函数; vector getjy() const{return jy;} //先返回一个vector对象,目前看不到图书数据,所以返回后,在操作类中使用.../*现在看不到图书数据,只能写出部分借阅,归还操作,在操作类中应判断是否具有罚款,...此函数仅用于修改学生,作为子函数使用*/ friend istream & operator>>(istream &in,Student & a); friend ostream & operator
首先,阅读之前要先搞清楚什么是运算符、函数重载。函数重载就是在一个范围内为一个函数声明多个实现方式,函数名必须一致。 那么C++运算符是否可以重载呢?可以!...先弄清什么时候需要进行运算符重载: 假设,你有一个类或者结构体,想通过 +、-、*、/ 这种最基本的运算符直接进行计算,又或者想用 ==、|| 直接进行比较。 这时候运算符重载的作用就来了。...下面一段代码是在一个类中对 = 进行了一个最简单的重载: void operator=(const DataPack &in) { this->name = in.name; this...->value + in.value; return out; }; 那么有哪些运算符可以重载呢?...+ b.value; return out; }; 但请注意,以下运算符只能作为成员函数进行重载: 运算符 说明 () 函数调用 [] 取下标 -> 成员访问 = 赋值 重载运算符的注意事项
, 有两种方式 , 一种是使用重载的 [] 操作符 , 另一种就是使用 at() 函数 ; 使用 迭代器 遍历字符串 : 使用 string::iterator 迭代器遍历字符串 ; 2、使用 数组下标...[] 遍历字符串 使用 数组下标 遍历字符串 , 主要调用 operator[] 运算符重载函数 实现 ’ 在 C++ 的 std::string 类中 , operator[] 函数 是一个成员函数...[] (int n); 该函数返回一个字符引用 , 表示字符串中位置为 n 的字符 ; 特别注意 : 该函数返回的是 字符的引用 , 因此可以直接用于 访问和修改 字符串中的字符 ; 代码示例 :...: const char& at(size_t pos) const; at() 函数返回一个常量字符引用 , 表示字符串中位置为 pos 的字符 ; 与 operator[] 运算符重载函数不同 ,...at() 函数在访问超出字符串范围的索引时会抛出 std::out_of_range 异常 ; 代码示例 : 下面的代码中 , 故意增加 1 字节, 令其抛出 std::out_of_range 异常
字符串比较 // 大于 和 小于 区别是 参数顺序不同的区别 return strcmp(this->m_p, s.m_p); } 2、重载 小于 < 运算符 使用 成员函数 实现 小于 < 运算符重载...s) { cin >> s.m_p; return in; } 在 String 内部类中 , 将 上述 全局函数 声明为 String 的 友元函数 ; // 使用 全局函数 实现 右移运算符...小于 < 运算符 bool String::operator<(String& s) { // 将 String 类比较转为 字符串比较 // 大于 和 小于 区别是 参数顺序不同的区别 return...// 在函数体中将 String 对象的 m_p 指针指向的数据输出到 out 输出流中 out << s.m_p << endl; // 该返回值还需要当左值使用 return out;...std; // 导入自定义的 String 类 #include "String.h" int main() { // 调用无参构造函数 String s1; // 调用有参构造函数
日期类 构造函数与获取天数 加天数 减天数 日期的比较 日期减日期 打印和输入日期 日期类完整代码 构造函数与获取天数 这里我们不算公元前的日期。...,你在加减天数的时候轻则月份会随之变化,重则年份也会随之变化,我们知道闰年和平年的2月不同,每个月和每个月的天数也不同,只有年和月是有规律的,所以可以写一个获取天数的函数,后续就可以用这个来判断你在某年某月加天数之后是否合法...Date s(2022, 10, 13); cout << s; cin和cout都是在头文件istream中定义的对象,cin是istream类,cout是osteram类的。...那么进行>重载的时候不会放入成员函数,因为在进行重载的时候,隐藏的this指针必定储存日期类的结构体,就会变成这个样子。..._day << "日" << endl; return out; } 在日期类进行了这个函数的友元,所以可以访问私有成员了。
第一次使用模板类型声明变量时,会创建类模板的一个实例, 以后定义同类型的变量时,会使用已经创建的第一个实例。 类模板有许多应用,最常见的应用是定义容器类。...类模板和类一样,可以有友元,其友元可以是类,函数或者其他模板。 如果一个派生类继承自该类模板,那么这个派生类也必须是模板。...;} }; 在类模板的内部,可以直接使用类模板名称,不需要显式地带模板参数,因此,在类模板的内部,Array和Array等价。...myArray; 二,类模板的成员函数 在类模板的模板体中定义的成员函数,与普通的类一样,成员函数可以看作是所有模板实例的内联函数。...但是在模板体的外部定义的成员函数,语法与普通的类不同,需要将成员函数定义为函数模板。 由于成员函数的函数模板与它们的类模板绑定在一起,所以函数模板使用的参数列表必须与类模板的参数列表完全相同。
一、容器思想 1、自定义类可拷贝 - 深拷贝与浅拷贝 上一篇博客 【C++】泛型编程 ⑬ ( 类模板示例 - 数组类模板 | 构造函数和析构函数 的 声明与实现 | 普通成员函数 的 声明与实现 | 外部友元函数...的问题 ; 下面的示例中 , 自定义类中的成员变量 char m_name[32] 是 在定义时 , 直接分配好的 , 如果 自定义类 中有 指针类型的成员变量 , 如 char* m_name , 涉及到...注明 泛型类型 // 实现时 , 不能在 函数名 和 参数列表之间 注明 泛型类型 friend ostream& operator (ostream& out, const... // 实现时 , 不能在 函数名 和 参数列表之间 注明 泛型类型 template ostream& operator& a) { for (int i = 0; i < a.m_length; i++) { // 在一行内输入数据, 使用空格隔开, 不换行 out << a.m_space
一、支持 数组类模板 存储的 自定义类 1、可拷贝和可打印的自定义类 在上一篇博客 中 , 定义了 可拷贝 与 可打印 的 自定义类 Student , 可以被存放到 数组类模板 中 ; 由于其 成员变量...和 有参构造函数中 , 使用 new 关键字 , 自动在堆内存中分配内存 , 然后为 堆内存 中的空间赋值 ; Student(){ m_age = 10; // 创建一个数组个数为 1 的数组...在析构函数中 , 需要将 使用 new 关键字申请的 堆内存进行释放 , 这里必须使用 delete 进行释放 ; 使用 malloc 申请的堆内存 , 必须使用 free 进行释放 ; 使用 new...首先 , 在类内部声明 重载左移运算符 的友元函数 ; class Student { friend ostream& operator<<(ostream& out, const Student&...s); } 然后 , 在 类外部 的 全局函数 中 , 实现 重载左移运算符函数 ; // 重载左移运算符实现 ostream& operator<<(ostream& out, const Student
<<(ostream& out, String& s)" << endl; // 在函数体中将 String 对象的 m_p 指针指向的数据输出到 out 输出流中 out << s.m_p <...< endl; // 该返回值还需要当左值使用 return out; } 同时 , 还要在 String 类中 , 将上述函数声明为 String 类的 友元函数 ; class String...& s); } 二、自定义类使用技巧 ---- 1、直接访问类的私有指针成员 在开发中 , 自定义了一个 class 类 , 其中定义了 指针 类型的 成员变量 ; 一般情况下 , 成员变量 都要 声明为...char* m_p; }; 2、为指针分配指定大小内存并初始化 0 在 有参构造函数 中 , 接收 int 类型的参数 , 该参数表示字符串大小 ; 如果 参数 为 0 , 则创建一个空字符串 ,...// 在函数体中将 String 对象的 m_p 指针指向的数据输出到 out 输出流中 out << s.m_p << endl; // 该返回值还需要当左值使用 return out;
,例如算术、相等性、关系和位运算符等,因此它们通常应该是普通的非成员函数 输入和输出运算符 IO库分别使用>>和<<执行输入和输出操作,并定义了其读写内置类型的版本,而类需要自定义适合其对象的新版本呢以支持...下标运算符 表示容器的类可以通过元素在容器中的位置访问元素,这些类一般会定义下标运算符operator[]。 下标运算符必须是成员函数。...根据point类型的不同,point->mem分别等价于: (*point).mem:point是一个内置的指针类型 point.operator()->mem:point是类的一个对象 函数调用运算符...类与旧版本中的unnary_function和binary_function没有关联,后两个类已经被更通用的bind函数替代了。...避免有二义性的类型转换 如果类中包含哪一个或多个类型转换,则必须确保在类类型和目标类型之间只存在唯一一种转换方式。否则我们编写的代码将很可能会具有二义性。
在这里需要介绍一下迭代器,在 string 类中,迭代器其实就是原生指针,迭代器的使用如下: #include #include using namespace...三、模拟实现 string 类 下面我们直接开始模拟实现 string 类的接口,在实现的过程中讲解用法,注意,我们只模拟比较常见和重要的接口。...拷贝构造函数 在这里的拷贝构造函数中,我们就需要回顾一下浅拷贝和深拷贝了,我们此前也在 类和对象(中篇) 了解过,现在来回顾一下。 浅拷贝: 也称值拷贝,编译器只是将对象中的值拷贝过来。..._capacity); } 在实现中,我们再利用标准库中的 swap 函数帮助我们完成 string 类的swap 函数。 使用和结果如下图: 4....流插入与流提取重载 在使用 string 的时候,为了方便查看字符串,我们可以重载流插入和流提取,方便打印查看字符串;在以前讲过,我们为了方便我们的使用以及体现流插入和提取的使用价值,我们要在类外面实现
类模板在表示支持多种数据结构显得特别重要,这些数据结构的表示和算法不受所包含的元素类型的影响。 ---- 类模板与继承: 1.父类是一般类,子类时模板类,和普通继承类似。...(不建议使用太多的友元函数) 类模板和友元函数: 在类外实现成员函数要先声明一下模板 #include using namespace std; template<typename...~A(); //友元函数在类中声明也要加上模板的声明 template friend A addA(const A& a, const A& b); private...---- 类模板和static数据成员 类外赋初值 template int A::count = 666; 虚拟类型T被实例化的类型不同,所调用的内容也不同。...自定义容器中存放自定义类对象,该容器重载了<<,想要按照下标cout<<,那么该类也要重载<<。
string的接口测试及使用 string类对象的访问及遍历操作 下标和方括号遍历 范围for遍历 迭代器遍历 相同的代码,在不同的编译器有不同的空间 string类对象的修改操作 string类非成员函数...++中,string类有两个成员函数size()和length(),它们都用于返回字符串的长度,但它们之间没有区别,可以互换使用。...这是因为C++标准库中的string类是基于字符数组实现的,它们都返回的是存储在string对象中的字符个数。因此,在C++中,size()和length()函数可以互相替代使用,没有区别。...是因为外部const的存在导致两个重载参数不一样,构成函数重载 下标和方括号遍历 以下是一个使用C ++的示例,使用下标和方括号来遍历string类的示例: #include #include...在循环体中,通过str[i]使用下标和方括号来访问字符串中的字符,并使用std::cout将其打印到控制台上。
这里通过 this 指针调用 , 不需要声明在参数中 ; 右操作数 : 右操作数 是 String b ; 该操作数需要声明在参数中 , 注意需要声明 引用类型 ; 上述两个是对象类型 , 对象一般传入...= b ; 左操作数 : 其中 左操作数 是 String a , 这里通过 this 指针调用 , 不需要声明在参数中 ; 右操作数 : 右操作数 是 String b ; 该操作数需要声明在参数中...return *this; } // 重载 数组下标 [] 操作符 char& String::operator[](int i) { cout << "调用重载 下标 [] 操作符函数 char...out, String& s) { cout << "调用重载 左移 << 操作符函数 ostream& operator<<(ostream& out, String& s)" << endl;...// 在函数体中将 String 对象的 m_p 指针指向的数据输出到 out 输出流中 out << s.m_p << endl; // 该返回值还需要当左值使用 return out;
语句后面可以有多个catch语句 不同类型的异常由不同的catch语句捕获,顺序从上往下严格匹配,不会进行隐式转换,比如: throw 1; //由int型的catch语句捕获 throw...举个例子,当我们调用第三方库的func()函数,但是该func()函数返回的异常是int型,每个异常值意义大有不同 (每次查看异常值都需要翻看文档手册才行) 所以我们可以在自己库创建一个myfunc(...如果catch中抛出的类型是类的情况 需要将捕获子类异常的catch放在上部 将捕获父类异常的cath放在下部, 避免子类异常当做父类异常来使用....(const string&) : 超出范围,比如数组下标越界 它们都有一个what()成员函数,用来返回一个字符串异常信息 -runtime_error 常用于程序中无法避免的恶性错误,...{ throw out_of_range("T& operator [] (int index)"); //抛出一个 out_of_range
领取专属 10元无门槛券
手把手带您无忧上云