C++语言-04-重载
相关概念
- 重载
- 在同一作用域中为某个函数和运算符指定多个定义,分别成为函数重载和运算符重载
- 重载声明
- 与之前已经在作用域内声明过的函数或方法具有相同名称的声明,参数列表和定义不同
- 重载决策
- 调用一个重载函数或重载运算符时,编译器需要比较调用函数时的参数类型与定义时的参数类型,来选择最合适的重载函数和重载运算符,这个过程称为重载决策
函数重载
规则
- 函数名相同
- 参数列表不同
- 与返回类型无关
示例
// 两个整数相加
int sum(int a, int b) {
cout << "sum of two int number: " << a + b << endl;
return a + b;
}
// 两个双精度小数相加
double sum(double a, double b) {
cout << "sum of two double number: " << a + b << endl;
return a + b;
}
int main(int argc, const char * argv[]) {
sum(1, 2); // 两个整数相加
sum(1.0, 2.0); // 两个双精度小数相加
sum(1, 2.0); //Call to 'sum' is ambiguous
return 0;
}
运算符重载
运算符的实质
- 带有特殊名称的函数
不可重载的运算符
运算符 含义 :: 作用于解析运算符 .* 成员对象选择运算符 . 以对象方式访问成员运算符 ?: 条件判断运算符 示例
一元运算符++
- 具有前缀形式和后缀形式,前缀形式的运算符重载函数没有参数,后缀形式的运算符重载函数具有参数
// 创建一个Apple的类
class AppleBasket {
private:
double appleWeight; // 苹果的重量
double priceOfPerKg; // 每千克苹果的价格
double totalPrices; // 苹果的总价格
public:
// set、get方法
void setAppleWeight(double weight) {
appleWeight = weight;
}
double getAppleWeight() {
return appleWeight;
}
void setPriceOfPerKg(double price) {
priceOfPerKg = price;
}
double getPriceOfPerKg() {
return priceOfPerKg;
}
double getTotalPrices() {
if (totalPrices == 0) { // 不打折
totalPrices = appleWeight * priceOfPerKg;
}
return totalPrices;
}
// 构造方法
AppleBasket() {
appleWeight = 0;
priceOfPerKg = 0;
}
AppleBasket(double priceOfPer, double weight) {
appleWeight = weight;
priceOfPerKg = priceOfPer;
}
// 运算符重载
/** 一筐苹果的重量自增 */
AppleBasket operator++() { // 前缀
AppleBasket apple;
apple.appleWeight = ++this->appleWeight;
apple.priceOfPerKg = this->priceOfPerKg;
return apple;
}
AppleBasket operator++(int) { // 后缀,参数必须是int
AppleBasket apple = *this;
this->appleWeight++;
return apple;
}
};
二元运算符+
/** 两筐苹果的重量相加 */
AppleBasket operator+(AppleBasket other) {
AppleBasket apple;
apple.appleWeight = this->appleWeight + other.appleWeight;
apple.priceOfPerKg = this->priceOfPerKg;
return apple;
}
赋值运算符=
- 通常用来创建一个新的对象
/** 赋值运算符 */
void operator=(AppleBasket other) {
appleWeight = other.appleWeight;
priceOfPerKg = other.priceOfPerKg;
}
逻辑运算符<
/** 比较this框苹果的重量是否小于other框苹果的质量 */
bool operator<(AppleBasket other) {
if (this->appleWeight < other.appleWeight) {
return true;
} else {
return false;
}
}
函数调用运算符
- 不是创建一种新的函数调用方式
- 实际上是创建了一个可以传递任意数目参数的运算符函数
/** 函数调用运算符 */
AppleBasket operator()(double w, double p, double totalP) {
AppleBasket apple;
apple.appleWeight = w;
apple.priceOfPerKg = p;
apple.totalPrices = totalP;
return apple;
}
类成员访问运算符->
- 通常用于为一个类赋予“指针”行为
- 重载的运算符函数,必须是一个成员函数,且返回类型必须是指针或者类的对象
- 运算符->通常与指针引用运算符*结合使用,用来实现“智能指针”的功能,通过智能指针访问对象,可以执行与普通指针不同的任务
// Apple类的容器
class AppleBasketContainer {
private:
vector<AppleBasket *> container;
public:
void add(AppleBasket *apple) {
container.push_back(apple);
}
// 友元类
friend class SmartPointer;
};
//AppleBasketContainer类的友元类
class SmartPointer {
private:
AppleBasketContainer appleContainer;
int index;
public:
// 构造函数
SmartPointer(AppleBasketContainer& ac) {
appleContainer = ac;
index = 0;
}
// 运算符重载
/** 返回值表示列表结束 */
bool operator++() { // 前缀版本
if (index > appleContainer.container.size()) return false;
if (appleContainer.container[++index] == 0) return false;
return true;
}
bool operator++ (int) { // 后缀版本
return operator++();
}
/** 重载运算符 -> */
Apple* operator->() {
if (!appleContainer.container[index]) {
cout << "Zero value!";
return (Apple*)0;
}
return appleContainer.container[index];
}
};
输入/输出运算符
- 通常将运算符重载函数定义为友元函数,使得在不创建对象的情况下调用函数
// 输入运算符
friend istream &operator>>(istream &input, AppleBasket &apple) {
cout << "请输入每kg苹果的价钱:";
input >> apple.priceOfPerKg;
cout << "请输入苹果的总重量:";
input >> apple.appleWeight;
apple.totalPrices = apple.appleWeight * apple.priceOfPerKg;
return input;
}
// 输出运算符
friend ostream &operator<<(ostream &output, const AppleBasket &apple) {
output << "每kg苹果的价格为:" << apple.priceOfPerKg << endl;
output << "苹果的总重量为:" << apple.appleWeight << endl;
output << "苹果的总价为:" << apple.totalPrices << endl;
return output;
}
下表运算符[]
- 通常用来增强数组的功能,如:数组越界检查
// 每个班级中最多的学生个数
const int MaxStudentCountOfPerTeacher = 45;
class Student {
private:
int studentId;
int age;
public:
// set,get方法
void setAge(int a) {
age = a;
}
int getAge() {
return age;
}
// studentId通常是自增的,不暴露set方法
int getStudentId() {
return studentId;
}
// 设置Teacher为Student的友元类,使Teacher可以访问Student的私有成员
friend class Teacher;
};
class Teacher {
private:
Student students[MaxStudentCountOfPerTeacher];
public:
// 构造函数
Teacher() {
for (int i = 0; i < 45; i++) {
students[i].studentId = i + 1;
}
}
// 运算符重载(数组越界检查)
Student operator[](int i) {
if (i >= MaxStudentCountOfPerTeacher) {
cout << "Index out of bounds" << endl;
return students[0];
}
return students[i];
}
};
重载运算符的简单使用
// 重载运算符的使用示例
int main(int argc, const char * argv[]) {
const int size = 10;
AppleBasket apples[size];
AppleContainer appleContainer;
// 初始化apples与appleContainer
for (int i = 0; i < size; i++) {
apples[i].setAppleWeight(i);
apples[i].setPriceOfPerKg(8.8);
appleContainer.add(&apples[i]);
}
// 创建一个迭代器
SmartPointer smartPointer(appleContainer);
do {
double totalPrice = smartPointer->getTotalPrices();
cout << "苹果的总价格为:" << totalPrice << endl;
} while (smartPointer++);
// 自增运算符++(前缀)
cout << "第一筐苹果的总价格为:" << (++apples[0]).getTotalPrices() << endl;
// 自增运算符++(后缀)
cout << "第二筐苹果的总价格为:" << (apples[0]++).getTotalPrices() << endl;
// 运算符+
cout << "前两筐苹果的总价为:" << (apples[0] + apples[1]).getTotalPrices() << endl;
// 逻辑运算符<
if (apples[0] < apples[1]) {
cout << "第一筐苹果的重量小于第二筐苹果的重量" << endl;
} else {
cout << "第一筐苹果的重量大于等于第二筐苹果的重量" << endl;
}
// 赋值运算符=
AppleBasket apple = apples[2];
cout << "第三筐苹果的重量为:" << apple.getAppleWeight() << endl;
// 函数调用运算符()
cout << "3kg苹果打折后的价格为:" << apple(3, 8.8, 20.0).getTotalPrices() << endl;
// 输入输出运算符<<,>>
cin >> apple;
cout << apple;
// 下标运算符[]
Teacher teacher;
Student student;
student = teacher[MaxStudentCountOfPerTeacher - 1];
cout << "最后一个学生的学号为:" << student.getStudentId() << endl;
student = teacher[MaxStudentCountOfPerTeacher];
cout << student.getStudentId() << endl;
return 0;
}
C++语言-04-重载的更多相关文章
- ActionScript语言函数重载
更新:你见过JavaScript支持重载吗,规范就是这么定义的.如果不是研究Java和Flex对象的Serialization,我也不会注意它. 距离写这篇文章已有8年了,时光匆匆啊,今天整理资料时看 ...
- C语言-04函数
1.参数 参数注意点 1.形式参数:定义函数时函数名后面中的参数,简称形参 2.实际参数:调用函数式传入的具体数据,简称实参 3.实参个数必须等于形参个数 4.函数体内部不能定义和形参一样的变量 5. ...
- C#语言-04.OOP基础
a. OOP:面对对象思想 i. 类:是一种功能强大的数据类型,而且是面向对象的基础 . 语法:访问修饰符 class 类名{ //类的主体 } . 成员变量:不以“函数”形式体现 a. 常量:代表与 ...
- C语言 04 进制
%d 或者%i 十进制 %c 输出字符 %p 输出地址 %f 输出小数 %o 八进制 %x 十六进制 一个int类型变量占4字节,占32bit(位) 例子:十进制 int=12 转二进制 0000 ...
- 重学C语言---04字符串和格式化输入/输出
1.程序示例 //talkback.c一个能为你提供一些信息的对话框 #include <stdio.h> #include <string.h> //提供strlen函数原型 ...
- Javascript函数重载,存在呢—还是存在呢?
1.What's is 函数重载? );//Here is int 10 print("ten");//Here is string ten } 可以发现在C++中会根据参数的类型 ...
- C语言面试题汇总之一
C语言面试题汇总之一 1.static有什么用途?(请至少说明两种) l 限制变量的作用域: 设置变量的存储域. 2.引用和指针有什么区别? 引用必须被初始化,指针不必: 引用初始化以后不能被改变,指 ...
- javascript arguments与javascript函数重载
1.所 有的函数都有属于自己的一个arguments对象,它包括了函所要调用的参数.他不是一个数组,如果用typeof arguments,返回的是’object’.虽然我们可以用调用数据的方法来调用 ...
- C++ 重载操作符与转换
<C++ Primer 4th>读书笔记 重载操作符是具有特殊名称的函数:保留字 operator 后接需定义的操作符号. Sales_item operator+(const Sales ...
- 【转】c++重载、覆盖、隐藏——理不清的区别
原文网址:http://blog.sina.com.cn/s/blog_492d601f0100jqqm.html 再次把林锐博士的<高质量c++编程指南>翻出来看的时候,再一次的觉得这是 ...
随机推荐
- java中三种方式获得类的字节码文件对象
package get_class_method; public class ReflectDemo { /** * @param args */ public static void main(St ...
- 2次成功投诉EMS和中国移动的经验
上个月要找房子,搬家很多事情,真实头疼...搬家还把腰闪了....现在还有点痛.然后中间碰到 移动宽带 移机的事情,搞得我非常火.然后想起去年投诉EMS的事情,在事情处理完成后,我果断总结了下来,让大 ...
- 剑指架构师系列-tomcat6通过伪异步实现connector
首先在StandardService中start接收请求的线程,如下: synchronized (connectors) { for (int i = 0; i < connectors.le ...
- [转载]浅谈组策略设置IE受信任站点
在企业中,通常会有一些业务系统,要求必须加入到客户端IE受信任站点,才能完全正常运行访问,在没有域的情况下,可能要通过管理员手动设置,或者通过其它网络推送方法来设置. 有了域之后,这项工作就可以很好的 ...
- iOS10新特性之CallKit开发详解:锁屏接听和来电识别
国庆节过完了,回家好好休息一天,今天好好分享一下CallKit开发.最近发现好多吃瓜问CallKit的VoIP开发适配,对iOS10的新特性开发和适配也在上个月完成,接下来就分享一下VoIP应用如何使 ...
- SQL中对XML的处理
DECLARE @PreSOMasterXML XMLDECLARE @SDA VARCHAR(100)SET @PreSOMasterXML=N'<ProcessTaskRequest& ...
- ok6410 android driver(7)
This article talk about how to test device driver on JNI. There are two ways to test the device driv ...
- DIV+CSS颜色边框背景等样式
1.使用css缩写 使用缩写可以帮助减少你CSS文件的大小,更加容易阅读.css缩写的主要规则请参看<常用css缩写语法总结>,css缩写的主要规则如下: 颜色 16进制的色彩值,如果每两 ...
- C# winform调用浏览器打开页面方法分享,希望对大家有帮助
在很多客户端程序中我们都需要调用浏览器打开网页,这里分享一个可以在我winform程序调用浏览器的方法,测试通过了. 声明:这个方法是上万个用户测试通过的,不是我没有测试通过就拿出来分享,那个是自己搬 ...
- csharp: 百度语音合成
public string API_id = "3333"; //你的ID public string API_record = null; public string API_r ...