侯捷C++高级编程(下)

news2024/9/22 11:28:28

对于1个类要么像指针要么像函数

主题1:转换函数

转换函数

/*
 * 1. 转换函数没有返回类型
 * 2. 转换函数一般需要加上const
 */
class Fraction
{
public:
     Fraction(int num,int den=1):m(num),n(den)
     {
         cout<<"Fraction(int num,int den=1): m/n = "<< m/n<<endl;
     }
     operator double()const
     {
         cout<<"调用转换函数double():"<<(double)( m/n )<<endl;
         return (double)( m/n );
     }
private:
    int m;
    int n;
};
int main(int argc, char** argv)
{
    Fraction f(8,2);
    double d = 5 + f;
    /*
     * 首先 4
     * */
//    Fraction d = f + 4;

    cout<<d<<endl;
    /*
     * 输出结果:
     * Fraction(int num,int den=1):m/n = 4
     * 调用转换函数double()
     * 8
     * 分析:f(8,2): 首先调用构造函数
     * 然后;5 + f 中的f调用转换函数转换为double
     */
}

non-explict-one-argument ctor

class Fraction
{
public:
    Fraction(int num,int den=1):m(num),n(den)
    {
        cout<<"Fraction(int num,int den=1): m/n = "<< m/n<<endl;
    }

    Fraction operator+(const Fraction &f)
    {
        cout<<"调用operator+()函数"<<endl;
        return Fraction(m+f.m,n+f.n);
    }
private:
   int m;
   int n;
};
int main(int argc, char** argv)
{
   Fraction f(8,2);
   Fraction d1 = f+5;// === f.operator+(5);
   /*
    * 首先f+5中的5调用构造函数Fraction(int num,int den=1)
    * 然后调用operator+()函数
    */
}

注意:提供默认值的构造函数可以将一种类中的为提供默认值的属性类型转换为该类类型---即将一种类型转化为本类类型 operaor double() --- 则是将本类型转化为double类型,两者转换方向刚好相反;但是我们一般所说的转换函数是后一种类型;
ambiguous error

class Fraction
{
public:
     Fraction(int num,int den=1):m(num),n(den)
     {
         cout<<"Fraction(int num,int den=1): m/n = "<< m/n<<endl;
     }
     operator double()const
     {
         cout<<"调用转换函数double():"<<(double)( m/n )<<endl;
         return (double)( m/n );
     }

     Fraction operator+(const Fraction &f)
     {
         cout<<"调用operator+()函数"<<endl;
         return Fraction(m+f.m,n+f.n);
     }
private:
    int m;
    int n;
};
Fraction operator+(int a,const Fraction &b)   
{
//解决5+f的问题
}
int main(int argc, char** argv)
{
    Fraction f(8,2);
    Fraction d1 = f+5;// Use of overloaded operator '+' is ambiguous (with operand types 'Fraction' and 'int')
    Fraction d1 = 5+f;
}

explict的使用:一般用在构造函数前面,表示此构造函数只能用于构造不能用于其他目的
explicit Fraction(int num,int den=1):m(num),n(den)
Fraction d1 = f+5;// error
但是仍然会出现:error: conversion from ‘double’ to non-scalar type ‘Fraction’ requested
解释:
f+5中首先由于在构造函数前面加上了explict所以不会ambiguous,f首先转换为double记为a,然后执行a+5后产生一个double记为c,但是c不能转化为Fraction,因为explict

:
Fraction operator+(int a,const Fraction &b)
{
//解决5+f的问题
}
是否可以成员函数实现,是否是下面的

class Fraction
{
	  friend  Fraction operator+(int a,const Fraction &f)
     {
         ;
     } //注意这不是Fraction的成员函数,这个是全局函数。只不过在Fraction中声明为友元函数之后直接实现了。
}
//这里的5+f的实现利用friend成员函数没有this指针的特点

关于友元函数

  1. 友元函数没有this指针
  2. 因为友元函数是类外的函数,所以它的声明可以放在类的私有段或公有段且没有区别。
  3. 友元函数是不能被继承的,就像父亲的朋友未必是儿子的朋友
    友元函数的分类:
    根据这个函数的来源不同,可以分为三种方法:
    普通函数友元函数:
    目的:使普通函数能够访问类的友元
    语法:
    声明: friend + 普通函数声明
    实现位置:可以在类外或类中
    实现代码:与普通函数相同
    调用:类似普通函数,直接调用
class INTEGER

 {

  friend void Print(const INTEGER& obj);//声明友元函数

 };

void Print(const INTEGER& obj)

{

   //函数体

}

void main()

{

  INTEGER obj;

  Print(obj);//直接调用

}

类Y的所有成员函数都为类X友元函数—友元类
目的:使用单个声明使Y类的所有函数成为类X的友元,它提供一种类之间合作的一种方式,使类Y的对象可以具有类X和类Y的功能。
语法:
声明位置:公有私有均可,常写为私有(把类看成一个变量)
声明: friend + 类名(不是对象哦)

class girl;

class boy

{

public:

  void disp(girl &);

};

void boy::disp(girl &x) //函数disp()为类boy的成员函数,也是类girl的友元函数

{

  cout<<"girl's name is:"<<x.name<<",age:"<<x.age<<endl;//借助友元,在boy的成员函数disp中,借助girl的对象,直接访问girl的私有变量

}

class girl

{

private:

  char *name;

  int age;

  friend boy; //声明类boy是类girl的友元

};

类Y的一个成员函数为类X的友元函数
目的:使类Y的一个成员函数成为类X的友元,具体而言:在类Y的这个成员函数中,借助参数X,可以直接以X的私有变量
语法:
声明位置:声明在公有中 (本身为函数)
声明:friend + 成员函数的声明
调用:先定义Y的对象y—使用y调用自己的成员函数—自己的成员函数中使用了友元机制
代码:
实现代码和2.4.2.3中的实现及其相似只是设置友元的时候变为friend void boy::disp(girl &);

主题2:pointer-like classes 智能指针

pointer-like classes 智能指针

template<class T>
class shared_ptr
{
public:
    T& operator*()const
    {
        return *px;
    }

    T* operator->()const
    {
        return px;
    }
    shared_ptr(T* p):px(p){};
private:
    T* px;
    long *pn;
};
struct FOO
{
    void method();
};
int main(int argc, char** argv)
{
    shared_ptr<FOO> sp(new FOO);
    FOO f(*sp);
    sp->method(); // == px->method(0)  ->会作用之后会继续出现->

    return 0;
}

pointer-like classes 迭代器

template <class T, class Refclass Ptr>
struct __list_iterator { //这是一个链表
    typedef __list_iterator<T, Ref, Ptr> self;
    typedef Ptr pointer;
    typedef Ref pointer;
    typedef __list_node<T>* link_type;
    link_type node;
    bool operator==(const self& x) const { return node == x.node; }
    bool operator==(const self& x) const { return node != x.node; }
    reference operator*() const { return (*node).data; }
    pointer operator-> const { return &(operator*())}
    self& operator++() { node = (link_type)((*node).next); return *this }
    self& operator++(int) { self tmp = *this; ++*this; return tmp; }
    self& operator--() { node = (link_type)((*node).prep); return *this }
    self& operator--(int) { self tmp = *this; --*this; return tmp; }
};

主题3: function-like classes 仿函数

template<class T>
struct identity
{
    const T& operator()(const T& x)const
    {
        return x;
    }
};

主题4:namespace

#include <iostream>
#include<list>

namespace jj01
{
//开始设计
	template<typename T>
	using Lst=list<T,allocator<T>>;
	void test()
}
int main()
{
	jj01::test()
}

主题6: 模板

class template,类模板

Function template 函数模板

member template 成员模板

template <class T1,class T2>
struct pair  {
  typedef T1 first_type;
  typedef T2 second_type;
  T1 first;
  T2 second;
  pair() :first(T1()),second(T2())  { }
  pair(const T1& a,const T2& b) :first(a), second(b)  {  }
  
  template <class U1,class U2>  //这里,模板套模板,成员模板
  pair(const pair<U1,U2>& p)
    : first(p.first),second(p.second)  {  }
};

class Base1{};
class Derived1:public Base1{};

pair<Derived1,Derived2> p;
pair<Base1,Base2> p2(p);
等价于pair<Base1,Base2> pw(pair<Derived1,Derived2>());  //用子类初始化父类

specialization 模板特化

template <class Key>
struct hash  {  };
--------------------上面的是泛化-------
template<>  //Key被锁定了
struct hash<char>  {
  size_t operator() (char x)  const  { return x;  }
}template<>  //Key被锁定了
strcut hash<int>  {
  size_t operator() (int x)  const  {return x;  }

template<>  //Key被锁定了
struct hash<long>  {
  size_t operator() (long x)  const  {  return x;  }
};

parti specialization 模板偏特化

个数的偏

在这里插入图片描述
因为上面的模板有两个参数,但是目前我只需一个值绑定一个

范围的偏

在这里插入图片描述

template template parameter 模板模板参数

在这里插入图片描述
XCIS<string,list> mylist1; 第一个确定为string,但是第二个不确定传入模板;但是是错误的;虽然 Container变为 list但是一些容器的模板有一个以上的参数,我们一般只是定义了一个参数,上面不通过是由于语法问题参数不足导致
在这里插入图片描述
打岔:由于unique和weak的一些特性导致错误。
在这里插入图片描述
上面不是模板模板参数,由于list已经指定模板了

variadic templates 数量不定的模板参数

void print()
{
    cout<<"------"<<endl;

}

template<typename T,typename ... Types>
void print(const T& firstArg,const Types&...args)
{//  参数:一个 + 一包
    cout<<firstArg<<endl;
    cout<<sizeof...(args)<<ends;
    print(args...);
}
int main()
{
    print(7.5,"hello",42);
    /*
7.5
2 hello
1 42
0 ------
     这个模板参数可变的函数:参数可以分为一个+一包,这个函数是递归调用
     首先是:print(first=7.5,args=("hello",42)) 然后输出firstArg,然后size...(args)==2
     然后是:print(first="hello",args=(42)),打印出“hello”然后size...(args)==1
     最后是:print(first=42,args=),打印42,然后size...(args)===1调用无参数的print()
     */
    return 0;
}

C++标准库

在这里插入图片描述

for(int i:{1,2,3,4})
	cout<<i;
//{1,2,3}是个容器

主题7:reference 引用

  1. object和其reference的大小相同,地址也相同(全都是假象)
  2. reference通常不用于声明变量,一般用于函数的参数类型和函数返回类型

主题8:对象模型

继承关系下的构造和析构

  1. 构造应该由内而外
  2. 析构应该由外二内

组合关系下的构造和析构

  1. 构造应该由内而外
  2. 析构应该由外二内

继承+组合 关系下的构造和析构

对象模型:vptr(虚指针)和vtbl(虚表)

  1. 只要一个类含有虚函数,那么该类一定含有虚指针。多一个虚函数就多一个虚指针
  2. 父类有虚函数子类一定有虚函数
    在这里插入图片描述
    函数:
  3. 静态绑定
  4. 动态绑定
    动态绑定的条件
  • 虚函数
  • 向上转型

this

主题9:const

  1. const只能放在成员函数后面

主题10:new delete

重载 operator new,operator new[],operator delete,operator delete[]

在这里插入图片描述

在这里插入图片描述
https://zhuanlan.zhihu.com/p/526244459

placement new

https://blog.csdn.net/qq_41453285/article/details/103547699

关于这里没有看明白(最后几节)

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

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

相关文章

[Leetcode - Python]704.二分查找(Easy)

1. 题目&#xff1a; 704.二分查找&#xff08;Easy&#xff09; 1代码&#xff1a; class Solution:def search(self, nums: List[int], target: int) -> int:left , right 0 ,len(nums)-1while left < right :mid (leftright)//2 # // 取整除&#xff0c;向…

Windows 安装 pandoc 将 jupyter 导出 pdf 文件

Windows 安装 pandoc 将 jupyter 导出 pdf 文件 1. 下载 pandoc 安装文件2. 安装 pandoc3. 安装 nbconvert4. 使用 pandoc 1. 下载 pandoc 安装文件 访问 https://github.com/jgm/pandoc/releases&#xff0c;下载最新版安装文件&#xff0c;例如&#xff0c;3.1.6.1 版&#…

【Kubernetes】Kubernetes之Pod详解

Pod 一、 Pod1. Pod 基础概念2. 在 Kubrenetes 集群中 Pod 使用方式2.1 pasue 容器2.2 kubernetes 中的 pause 容器提供的功能 3. Pod 的概念和结构组成4. Pod 的分类5. Pod 容器的分类5.1 基础容器&#xff08;infrastructure container&#xff09;5.2 初始化容器&#xff08…

【效率提升—Python脚本】根据Verilog文件自动生成tb文件

文章目录 Verilog端口文件&#xff08;仅做示范用&#xff09;对应的tb文件相应代码 在数字IC设计过程中&#xff0c;根据顶层生成testbench时存在很多重复性工作&#xff0c;因此为了提高工作效率&#xff0c;特地开发此脚本。 Verilog端口文件&#xff08;仅做示范用&#xf…

Centos7离线安装MySQL8

1、下载MySQL https://downloads.mysql.com/archives/community/ 2、下载完毕后&#xff0c;上传到Centos&#xff0c;解压 tar -xf mysql-8.0.33-1.el7.x86_64.rpm-bundle.tar 3、逐条执行安装命令 rpm -ivh mysql-community-common-8.0.33-1.el7.x86_64.rpm rpm -ivh …

C++的vector

文章目录 迭代器失效问题构造函数赋值运算符begin() end()size() capacity() empty()reserve()operator[ ]insert()erase()resize() 迭代器失效问题 迭代器失效,实际就是迭代器底层对应指针所指向的空间被销毁了,而使用一块已经被释放的空间 1.扩容导致迭代器失效问题 在对…

JVM工作的总体机制概述

JDK、JRE、JVM关系回顾 JVM&#xff1a;Java Virtual Machine&#xff0c;翻译过来是Java虚拟机JRE&#xff1a;Java Runtime Environment&#xff0c;翻译过来是Java运行时环境 JREJVMJava程序运行时所需要的类库JDK&#xff1a;Java Development Kits&#xff0c;翻译过来是…

数据结构【图的类型定义和存储结构】

数据结构之图 图的定义和概念图的定义图的术语 图的类型定义图的存储结构数组&#xff08;邻接矩阵&#xff09;表示法无向图的邻接矩阵表示法有向图的邻接矩阵表示法网&#xff08;即有权图&#xff09;的邻接矩阵表示法 邻接矩阵的ADT定义邻接表&#xff08;链式&#xff09;…

测试经典书籍拆分讲解

一、全程软件测试 测试行业的经典书籍 测试方法测试策略领域测试主流测试技术涵盖了软件测试的流程与方法体系 二、探索式测试 探索式测试的经典代表性书籍探索式测试是业务测试和手工测试实践中的一个方法论 三、Google测试之道 高级测试工程师与架构师必读讲解google的测…

(学习笔记-进程管理)进程间有哪些通信方式?

每个进程的用户地址空间都是独立的&#xff0c;一般而言是不能互相访问的&#xff0c;但内核空间时每个进程都共享的&#xff0c;所以进程之间要通信必须通过内核 管道 在Linux命令中 [ | ] 这个竖线就是一个管道。 $ ps auxf | grep mysql 它的功能是讲前一个命令&#xf…

8月9日上课内容 nginx负载均衡

负载均衡工作当中用的很多的&#xff0c;也是面试会问的很重要的一个点 负载均衡&#xff1a;通过反向代理来实现&#xff08;nginx只有反向代理才能做负载均衡&#xff09; 正向代理的配置方法&#xff08;用的较少&#xff09; 反向代理的方式&#xff1a;四层代理与七层代…

C语言:打开调用堆栈

第一步&#xff1a;打断点 第二步&#xff1a;FnF5 第三步&#xff1a;按如图找到调用堆栈

DC-8靶机

DC-8官网地址 信息收集 靶机MAC&#xff1a; 00:0C:29:3A:46:A1 主机发现 nmap -sP 192.168.80.0/24端口扫描 nmap -A -p- 192.168.80.142访问80端口 点击页面能点击的地方&#xff0c;发现每点击一个链接&#xff0c;地址栏的?nid后面的数字就会变 尝试在数字后面加个 引…

【Leetcode】链表中两数之和(模拟加法器)(击败100%)

step by step. 题目&#xff1a; 给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。 请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外&…

2023年下半年软考初级程序员备考攻略

初级程序员考试科目包含基础知识和应用技术&#xff0c;各科目的考试形式都是笔试&#xff0c;满分均为75分。程序员考试需要各科目在一次考试中均及格才算合格&#xff0c;单科及格的成绩不保留&#xff0c;也不能转移到下次考试时使用。 这里给大家理清一个程序员考试的相关…

iOS开发-JsonModel的学习及使用

IOS JsonModel的学习及使用 当我们从服务端获取到json数据后的时候&#xff0c;我们需要在界面上展示或者保存起来&#xff0c;下面来看下直接通过NSDictionary取出数据的情况。 NSDictionary直接取出数据的诟病。 NSString *name [self.responseObj objectForKey:"nam…

Vue3弹出确认(Popconfirm)

效果如下图&#xff1a;在线预览 APIs 参数说明类型默认值必传title确认框的标题string | slot‘’falsedescription确认框的内容描述string | slot‘’falsecontent展示的文本string | slot‘’falseicon自定义弹出确认框 Icon 图标string | slot‘’falsemaxWidth弹出确认框…

《合成孔径雷达成像算法与实现》Figure3.8

与图3.7的代码区别只在于原始信号的表达式对了一个时间偏移 代码复现如下&#xff1a; clc clear all close all%参数设置 TBP 100; %时间带宽积 T 10e-6; %脉冲持续时间 tc …

SEED-Bench: Benchmarking Multimodal LLMs with Generative Comprehension

本文是LLM相关的文章&#xff0c;针对《SEED-Bench: Benchmarking Multimodal LLMs with Generative Comprehension》的翻译。 SEED-基准&#xff1a;用生成理解对多模式LLM进行基准测试 摘要1 引言2 相关工作3 SEED-Bench 摘要 基于强大的大型语言模型&#xff08;LLM&#…

【SpringBoot框架篇】33.优雅集成i18n实现国际化信息返回

文章目录 1.简介2.MessageSource配置和工具类封装2.1.配置MessageSource相关配置2.2.配置工具类2.3.测试返回国际级文本信息 3.不优雅的web调用示例(看看就行&#xff0c;别用)4.优雅使用示例4.1.错误响应消息枚举类4.2.ThreadLocal工具类配置4.2.1.ThreadLocal工具类数据封装4…