2、函数重载和覆盖、动态内存分配、引用

news/2024/7/23 10:46:00 标签: c++

函数重载和覆盖

重载关系的产生:

  • 同一作用域内
  • 函数名必须相同
  • 形参表必须不同

重载关系的函数的调用

  • 根据实参类型和形参的类型进行匹配,调用最匹配的函数

重载和隐藏

  • 只有同一作用域内的同名函数才涉及重载的关系
  • 不同作用域同名函数涉及的是隐藏关系
// 详谈同一作用域
#include <iostream>
using namespace std;
namespace ns1{
    void foo( char* c, short s){
        cout << "1. foo(char*, short)" << endl;
    }

    void foo( int i, double d){
        cout << "2. foo(int, double)" << endl;
    }
}

namespace ns2{
    void foo( const char* c, short s){
        cout << "3. foo(const char*, s)" << endl;
    }

    void foo( double d, int i ){
        cout << "4. foo(double, int)" << endl;
    }
}

int main( void ){
	// 名字空间指令,从这行代码开始,ns1中的内容在当前作用域可见(出现在可见表中)
    using namespace ns1; 
	// 名字空间声明,从这行代码开始,ns2中的foo引入当前作用域(出现在定义表中)
    using ns2::foo;  
    //名字同时出现在定义表和可见表时,先从定义表读取,忽略可见表
    char* c; short s;
    foo( c, s );   // 3
    return 0;
}

重载解析

  • 完全匹配>常量转换>升级转换>标准转换>自定义转换>省略号匹配

函数指针的类型决定其调用的哪个版本的重载函数

// 重载匹配的优先级
#include <iostream>
using namespace std;

void foo( char* c, short s){            // 完全匹配  _Z3fooPcs
    cout << "1. foo(char*, short)" << endl;
}

void foo(const char* c, short s){       // 常量转换  _Z3fooPKcs
    cout << "2. foo(const char*,short)" << endl;
}

void foo(char* c, int s){               // 升级转换  _Z3fooPci
    cout << "3. foo(char*,int)" << endl;
}

void foo(char* c, char s){              // 标准转换  _Z3fooPcc
    cout << "4. foo(char*,char)" << endl;
}

void foo( ... ){                        // 省略号匹配 _Z3fooz
    cout << "5. foo( ... )" << endl;
}
int main( void ){
    char* c; short s;
    // 普通方式调用重载关系的函数,根据实参类型和形参类型匹配,来确定调用哪一个foo      1
    foo( c, s );  

    void (*pfunc)(const char*,short) = foo;  // _Z3fooPKcs
    // 函数指针方式调用重载关系的函数,根据函数指针本身的类型,来确定调用哪一个foo      2
    pfunc(c,s);   
    return 0;
}

重载是通过C++换名机制来实现的
在这里插入图片描述
通过extern“C”可以要求C++编译器按照C方式编译函数,即不做换名,当然也就无法重载。

动态内存分配

new /delete会在堆中分配和释放内存
注意事项:

  • 不能通过delete释放已经释放过的内存
  • delete野指针的后果未定义,但是delete空指针是安全的
  • new申请内存失败,会抛出异常
int * pi = new int;
delete pi;//野指针,对它再次delete的后果很严重
pi=NULL;//空指针,对它再次delete是安全的

分配内存的同时初始化

int * pi = new int(10);

数组
在这里插入图片描述

int* pi = new int[4]{10,20,30,40};

delete[] pi;

多维数组

  • 通过new分配的N维数组,返回N-1维数组指针
int (*prow)[4] = new int[3][4]
int (*ppage)[4][5] = new int[3][4][5]
// 动态(堆)内存分配
#include <iostream>
#include <cstdlib>
using namespace std;

int main( void ){
//    int* pm = (int*)malloc( 4 );
//    cout << "*pm=" << *pm << endl;  // 初始值为0
//    free( pm );  // 当这行代码执行完毕后,pm指向的堆内存被释放,进而pm变为野指针
//    pm = NULL;
//    free( pm );  // 给free传递的为野指针,释放野指针后果很严重,释放空指针是安全的
//
//    int* pn = new int(100);
//    cout << "*pn=" << *pn << endl;
//    delete pn; // 当这行代码执行完毕后,pn指向的堆内存被释放,进而pn变为野指针
//    pn = NULL;
//    delete pn; // 给delete传递的为野指针,释放野指针后果很严重,释放空指针是安全的
//
    int* pi = new int[4]{10,20,30,40}; // 以数组的方式来new,返回的永远是第一个元素的地址
    for( int i = 0; i < 4; i++)
        cout << pi[i] << ' ';
    cout << endl;
    delete[] pi;
    pi = NULL;

    // 不管是几维数组,都应该当做一维数组看待
    int(*p)[4] = new int[3][4]{{1,2,3,4},{11,22,33,33},{111,222,333,333}}; // 以数组的方式来new,返回的永远为第一个元素的地址
    /*
    int (*p)[4] = a;//声明定义一个 拥有3个一维数组(int[4])的数组指针
    *p指向第一个元素的地址,即第一个一维数组的地址
    */

    cout << (*p)[1] << endl; //2  (*p)[1] 代表访问第1个一维数组的第2个元素
    cout << p[1][2] << endl; // 33 p[1][2] 代表访问第2个一维数组的第3个元素



    cout << endl;
    delete[] p;

//    try{
//        new int[0xFFFFFFFFFFFF];
//    }
//    catch(...){
//    }
    return 0;
}

引用

  • 引用即内存的别名
  • 引用本身不占内存,并非实体,对引用的所有操作都是在对目标内存进行操作
  • 引用必须初始化,且不能更换目标
  • 不存在引用的引用
  • 引用的常属性必须和目标的常属性一致
  • 引用可以限定更加严格
  • 常引用可以引用右值:延长右值的生命周期
  • 常引用 为 万能引用。
int a=10;
int& b=a;

int c = 20;
b = c;//仅仅是在对引用的目标内存进行赋值
#include <iostream>
using namespace std;

int main( void ){
    int a = 10;
    int& b = a; // 这并不是利用a的数据给b赋值,而应该理解为引用b是a所代表的内存的别名
    int& d = b; // 这并不是引用的引用,而应该理解为d是b的目标内存的引用,也就是说,d是a的引用
    cout << "&a:" << &a << ", &b:" << &b << ", &d:" << &d << endl;

    const int e = 10;
//  int& f = e;  // error 别名不可以比真名限定的更加宽松
    const int& g = e;  // ok

    const int& h = a; // ok, 别名可以比真名限定的更加严格
    return 0;
}

http://www.niftyadmin.cn/n/5238892.html

相关文章

CVPR 2023 精选论文学习笔记:Cross-Domain Image Captioning With Discriminative Finetuning

我们首先根据 MECE 原则给出本文选题的四个特征: 1. 数据标注。数据标注是将标签或元数据添加到数据的过程。在图像描述中,数据标注涉及将图像与其对应的自然语言描述进行标记。在研究中使用的数据标注类型会对图像描述模型的性能和泛化能力产生重大影响。 配对图像-描述数据…

【降本增笑?滴滴史上最严重服务故障,裁员真不能裁测试】

2023 年 11 月 27 日晚间&#xff0c;滴滴因系统故障导致 App 服务异常&#xff0c;不显示定位且无法打车。11 月 27 日晚&#xff0c;滴滴出行进行了回复&#xff1a;非常抱歉&#xff0c;由于系统故障。 前言 2023 年 11 月 28 日早间&#xff0c;滴滴出行消息称&#xff0c;…

Python 3 使用 write()、writelines() 函数写入文件

1 使用 write() 函数&#xff0c;将字符串&#xff08;或字节串&#xff0c;仅适用写入二进制文件中&#xff09;写入文件中。 with open(example.txt,w,encodingutf-8) as f:f.write(春夜喜雨\n)f.write(杜甫 [唐代]\n)f.write(好雨知时节&#xff0c;当春乃发生。\n)f.write(…

基于jsp的搜索引擎

摘 要 随着互联网的不断发展和日益普及&#xff0c;网上的信息量在迅速地增长&#xff0c;在2004年4月&#xff0c;全球Web页面的数目已经超过40亿&#xff0c;中国的网页数估计也超过了3亿。 目前人们从网上获得信息的主要工具是浏览器&#xff0c;搜索引擎在网络中占有举足轻…

【LeetCode 0151】【字符串】反转字符串中的单词

题目 https://leetcode.com/problems/reverse-words-in-a-string/ 题解 正则高阶函数 var reverseWords function(s) {return s.split(/[\s]/).filter(e>e!"").reverse().join(" ") };迭代双指针&#xff08;时间O(n) 空间O(n) &#xff09;&am…

Android,JNI开发和NDK之间的联系

Android&#xff0c;JNI开发和NDK。 1.jni和ndk jni是在jdk中就有出现的 在我们jdk路径中 D:\java\jdk11\include 这就是jdk中的jni Android开发环境中的ndk也有jni&#xff0c; D:\Android\sdk\ndk\20.0.5594570\toolchains\llvm\prebuilt\windows-x86_64\sysroot\usr\in…

运维03:LAMP

黄金架构LAMP 什么是LAMP LAMP是公认的最常见&#xff0c;最古老的黄金web技术栈 快速部署LAMP架构 #停止nginx&#xff0c;并且把nginx应用卸载了 systemctl stop nginx yum remove nginx -y#关闭防火墙 iptables -F #清空防火墙规则&#xff0c;比如哪些请求允许进入服…

【Linux】编译器-gcc/g++与调试器-gdb的使用

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 目录 前言 1.gcc/g语法 2.gcc的使用及…