详解C++之函数重载

函数重载本质

c++中通过函数名和函数确定一个函数
所以相同的函数名,不同参数也是可以的
不同于c语言,c语言没有函数重载,函数的本质地址就是函数名
函数重载发生在同一个作用域内

类中的重载

构造函数重载
普通成员函数重载
静态成员函数重载

全局函数、静态成员函数、普通成员函数可以发生重载吗?

本质就是函数名和函数参数不同,并且发生在同一个作用域
静态函数和普通成员函数是可以的
全局函数作用域在全局作用域,所以不可以

问题1:当父类的成员函数和子类的成员函数相等,会发生重载吗?

本质还是上面说的,因为父类和子类的作用域不在同一个

看一段代码

 #include <iostream>

class father{
public:
 father() {
  std::cout << "father()" << std::endl;
 }
 void print() {
  std::cout << "father print" << std::endl;
 }
};

class child : public father{
public:
 child() {
  std::cout << "child()" << std::endl;
 }
 void print(int a) {
  std::cout << "child print = " << a << std::endl;
 }
};

int main(){
 father* father_test = new father();
 father_test->print(); //打印father print

 child* child_test2 = new child();
 child_test2->print(); //编译错误no matching function for call to 'child::print()'

 return 0;
}

由打印输出可得第一个打印属于father正常输出,没问题,第二个打印是编译错误,我们其实想访问的是父类的print,但是由于子类定义了print,那么在子类的作用域中,print这个函数现在只存在一个,那就是void print(int a),如果想调用父类的就要显示指定child_test2->father::print();

问题2,子类可以重写父类的函数吗,或者说定义相同的?

看代码

#include <iostream>

class father{
public:
 father() {
  std::cout << "father()" << std::endl;
 }
 void print() {
  std::cout << "father print" << std::endl;
 }
};

class child : public father{
public:
 child() {
  std::cout << "child()" << std::endl;
 }
 void print() {
  std::cout << "child print" << std::endl;
 }
};

int main(){
 father* father_test = new father();
 father_test->print(); //打印father print

 child* child_test2 = new child();
 child_test2->print(); //child print

 return 0;
}

可见是可以定义相同的函数,并重写的

问题3,当全局运算符重载遇上类中的运算符重载,优先级是什么

 #include <iostream>
class child;
class father{
public:
 father() {
  std::cout << "father()" << std::endl;
 }
 bool operator==(const father& e) {
  std::cout << "void print(const father& e)" << std::endl;
 }
};
bool operator==(const father& e1, const father& e2) {
 std::cout << "void print(const child& e1, const child& e2)" << std::endl;
}

class child : public father{
public:
 child() {
  std::cout << "child()" << std::endl;
 }
};

int main(){
 child child1_test;
 child child2_test;

 child1_test==child2_test;
 return 0;
}

输出为void print(const father& e)类中的运算符重载优先级大于全局

当复制兼容遇上全局重载呢?

#include <iostream>
class child;
class father{
public:
 father() {
  std::cout << "father()" << std::endl;
 }
 bool operator==(const father& e) {
  std::cout << "void print(const father& e)" << std::endl;
 }
};
bool operator==(const child& e1, const child& e2) {
 std::cout << "void print(const child& e1, const child& e2)" << std::endl;
}

class child : public father{
public:
 child() {
  std::cout << "child()" << std::endl;
 }
};

int main(){
 child child1_test;
 child child2_test;

 child1_test==child2_test;
 return 0;
}

打印:"void print(const child& e1, const child& e2)"

仅仅变化了,全局的函数参数类型,正常来说类中和全局的==都是可以的,但是当类中的需要一个默认的转换,子类到父类,全局的是直接类型就对的上的,编译器就优先使用全局的

说到运算符重载,我们现在定义函数实现类的功能有三种选择:成员函数,全局函数,全局函数+友元函数

1.看是否需要虚函数,如果需要虚函数,那么肯定是类的成员函数

2.看是否定义的是<<或者>>运算符,我们都知道打印输出是全局<<,但是为什么呢,看一下实际的原型针对String而言ostream& operator<<(ostream& output, const String& string)我们使用的时候就是 std::cout << "haha";
如果定义为类中的就是ostream& operator<<(ostream& output)使用起来就是 "haha"<<"std::cout"看出差别了吧,如果定义在类中使用起来就很别扭,继续上面的结果,如果是<<或者>>运算符,然后如果需要访问private域,那么就把全局函数变为类对应的友元函数

3.当需要对左边的参数进行类型转换,需要定义全局函数,因为类中操作符函数,左边的就是类本身,如果需要访问private域,那么就把全局函数变为类对应的友元函数

4.其他情况为类的成员函数

以上就是详解C++之函数重载的详细内容,更多关于c++之函数重载的资料请关注我们其它相关文章!

(0)

相关推荐

  • C++中的四个默认成员函数与运算符重载详解

    本文主要给大家介绍了关于C++默认成员函数与运算符重载的相关内容,分享出来公的敬爱啊参考学习,话不多说,来一起看看详细的介绍: 一:类和对象的基础知识:类的定义,访问限定符,面向对象封装性,对象的大小计算等等.(编译环境为VS2015) 面向对象程序设计: 概念:(Object Oriented Programming,缩写:OOP)是一种程序设计范型,同时也是一种程序开发的方法.对象指的是类的实例,将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性.灵活性和扩展性. 类:类的基

  • C++语法中的函数重载和默认参数

    C语言中没有函数重载 C++语言中有函数重载 函数名相同,参数个数不同.参数类型不同.参数顺序不同 例如下面就是函数重载 void sum(int a, int b){ cout << a+b << endl; } void sum(int a, double b){ cout << a+b << endl; } 返回值类型与函数重载无关 返回值类型与函数重载无关,下面代码不构成重载,编译会报错 //返回值类型与函数重载无关 int func(){ retu

  • 详解c/c++赋值函数(重载=号运算符)

    首先c++里的各种运算符都是用函数实现的,比如=,就等号函数. 所以当用=给一个对象赋值的时候,实际调用的是=号所对应的=号函数. 分析下面的代码 #include <iostream> using namespace std; class Test{ public: explicit Test(){ data = 0; } explicit Test(int d):data(d){ cout << "C:" << this << &qu

  • C++中函数重载实例详解

    C++中函数重载实例详解 函数重载: 1.具有相同的名称,执行基本相同的操作,但是使用不同的参数列表. 2.函数具有多态性. 3.编译器通过调用时参数的个数和类型确定调用重载函数的哪个定义. 4.只有对不同的数据集完成基本相同任务的函数才应重载. 函数重载的优 点 1.不必使用不同的函数名 2.有助于理解和调试代码 3.易于维护代码 接下来直接上代码: #include <iostream> using namespace std ; void say_hello(void) { cout &

  • C++深入学习之彻底理清重载函数匹配

    前言 前面我们讲到了<函数重载>,有了函数重载之后,就需要确定某次调用需要选用哪个函数.这个过程可以称之为函数匹配或者重载确定.大多数情况下,我们都很容易能够确定某次调用需要选用哪个函数,但事实上不尽然.但通过本文将彻底理清重载函数匹配 匹配过程 为便于说明,将函数匹配分为三个阶段,确定候选函数,确定可行函数,确定最佳匹配函数. 确定候选函数 候选函数也就是和被调用的函数同名,并且其声明在调用点可见.举个简单的例子. 假设有两个文件,1.cpp和2.cpp,内容分别如下: 1.cpp: //函

  • C++基础学习之函数重载的简单介绍

    前言 我们在平时写代码中会用到几个函数但是他们的实现功能相同,但是有些细节却不同.例如:交换两个数的值其中包括(int, float,char,double)这些个类型.在C语言中我们是利用不同的函数名来加以区分. void Swap1(int* a, int* b); void Swap2(float* a, float* b); void Swap3(char* a, char* b); void Swap4(double* a, double* b); 我们可以看出这样的代码不美观而且给程

  • C++默认参数与函数重载及注意事项

    一.默认参数 在C++中,可以为参数指定默认值.在函数调用时没有指定与形参相对应的实参时, 就自动使用默认参数. 默认参数的语法与使用: (1)在函数声明或定义时,直接对参数赋值.这就是默认参数: (2)在函数调用时,省略部分或全部参数.这时可以用默认参数来代替. 注意: (1)默认参数只可在函数声明中设定一次.只有在没有函数声明时,才可以在函数定义中设定.(#add ,此句意为存在函数声明和定义两部分的时候.验证表明有这个限制,可以随便,但出于规范,在声明中指定) (2)如果一个参数设定了缺省

  • C++中const用于函数重载的示例代码

    常成员函数和非常成员函数之间的重载 首先先回忆一下常成员函数 声明:<类型标志符>函数名(参数表)const: 说明: (1)const是函数类型的一部分,在实现部分也要带该关键字. (2)const关键字可以用于对重载函数的区分. (3)常成员函数不能更新类的成员变量,也不能调用该类中没有用const修饰的成员函数,只能调用常成员函数. (4)非常量对象也可以调用常成员函数,但是如果有重载的非常成员函数则会调用非常成员函数. 重载看例子: #include<iostream> u

  • 详解C++之函数重载

    函数重载本质 c++中通过函数名和函数确定一个函数 所以相同的函数名,不同参数也是可以的 不同于c语言,c语言没有函数重载,函数的本质地址就是函数名 函数重载发生在同一个作用域内 类中的重载 构造函数重载 普通成员函数重载 静态成员函数重载 全局函数.静态成员函数.普通成员函数可以发生重载吗? 本质就是函数名和函数参数不同,并且发生在同一个作用域 静态函数和普通成员函数是可以的 全局函数作用域在全局作用域,所以不可以 问题1:当父类的成员函数和子类的成员函数相等,会发生重载吗? 本质还是上面说的

  • 一文详解C++子类函数为什么不能重载父类函数

    先说结论: 子类成员函数的函数名和基类一样,但是函数声明与基类不一样的时候,不会和基类函数构成重载,而是会隐藏基类函数 简要回顾下C++中的基本概念: 重写(override): 基类函数带virtual,子类函数声明和基类完全一样,实现不一样重 载(overload): 同一个类中,函数名一样,函数参数类型,个数,顺序等不一样的构成重载 隐藏(hide): 子类函数名和基类一样,但是函数声明与基类不一样,就会对基类的函数进行隐藏 那么,子类函数名和基类一样,但是函数声明与基类不一样的时候,为什

  • 详解C++赋值操作符重载

    1.赋值操作符重载的原因 赋值操作符是一个使用频率最高的操作之一,通常情况下它的意义十分明确,就是将两个同类型的变量的值从一端(右端)传到另一端(左端).但在以下两种情况下,需要对赋值操作符进行重载. 一是赋值号两边的表达式类型不一样,且无法进行类型转换. 二是需要进行深拷贝. 2. 赋值操作符重载的注意事项 赋值操作符只能通过类的成员函数的形式重载.这就说明了,如果要将用户自定义类型的值传递给基本数据类型的变量,只能通过类型转换机制,而不能利用重载来实现. 当赋值号两边的表达式不一致的时候,可

  • 一文详解C#中方法重载的底层玩法

    目录 一:为什么 C 不支持 二:C++ 符号表突破 三:C#如何实现突破 最近在看 C++ 的方法重载,我就在想 C# 中的重载底层是怎么玩的,很多朋友应该知道 C 是不支持重载的,比如下面的代码就会报错. #include <stdio.h> int say() { return 1; } int say(int i) { return i; } int main() { say(10); return 0; } 从错误信息看,它说 say 方法已经存在了,尴尬... 一:为什么 C 不支

  • 详解C++中函数模板的定义与使用

    目录 1. 前言 2. 初识函数模板 2.1 语法 2.2 实例化 2.3 实参推导 3. 重载函数模板 1. 前言 什么是函数模板? 理解什么是函数模板,须先搞清楚为什么需要函数模板. 如果现在有一个需求,要求编写一个求 2 个数字中最小数字的函数,这 2 个数字可以是 int类型,可以是 float 类型,可以是所有可以进行比较的数据类型…… 常规编写方案:针对不同的数据类型编写不同的函数. #include <iostream> using namespace std; //针对 int

  • 详解C语言函数返回值解析

    详解C语言函数返回值解析 程序一: int main() { int *p; int i; int*fun(void); p=fun(); for(i=0;i<3;i++) { printf("%d\n",*p); p++; } return 0; }; int* fun(void) { static int str[]={1,2,3,4,5}; int*q=str; return q; } //不能正确返回 虽然str是在动态变量区,而该动态变量是局部的,函数结束时不保留的.

  • 详解Python map函数及Python map()函数的用法

    python map函数 map()函数 map()是 Python 内置的高阶函数,它接收一个函数 f 和一个 list,并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回. 例如,对于list [1, 2, 3, 4, 5, 6, 7, 8, 9] 如果希望把list的每个元素都作平方,就可以用map()函数: 因此,我们只需要传入函数f(x)=x*x,就可以利用map()函数完成这个计算: def f(x): return x*x print map(f,

  • 详解C++虚函数的工作原理

    静态绑定与动态绑定 讨论静态绑定与动态绑定,首先需要理解的是绑定,何为绑定?函数调用与函数本身的关联,以及成员访问与变量内存地址间的关系,称为绑定. 理解了绑定后再理解静态与动态. 静态绑定:指在程序编译过程中,把函数调用与响应调用所需的代码结合的过程,称为静态绑定.发生在编译期. 动态绑定:指在执行期间判断所引用对象的实际类型,根据实际的类型调用其相应的方法.程序运行过程中,把函数调用与响应调用所需的代码相结合的过程称为动态绑定.发生于运行期. C++中动态绑定 在C++中动态绑定是通过虚函数

  • 详解JavaScript匿名函数和闭包

    概述 在JavaScript前端开发中,函数与对其状态即词法环境(lexical environment)的引用共同构成闭包(closure).也就是说,闭包可以让你从内部函数访问外部函数作用域.在JavaScript,函数在每次创建时生成闭包.匿名函数和闭包可以放在一起学习,可以加深理解.本文主要通过一些简单的小例子,简述匿名函数和闭包的常见用法,仅供学习分享使用,如有不足之处,还请指正. 普通函数 普通函数由fucntion关键字,函数名,() 和一对{} 组成,如下所示: function

  • 详解JavaScript自定义函数

    一.定义方法:在Javascript中必须用function关键字 function funcName(arg1,arg2...) { statements; return "变量值"; //返回值可以根据函数的需要 } 函数名是函数自身的一个引用.此种方式创立的函数引用是独立存在的,无法删除. 1.调用函数:函数名(参数列表). 传递的参数不必与函数定义的参数个数一致,并且可以设定函数参数的默认值. function example(a,b){ var a = arguments[0

随机推荐