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

对于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{privatechar *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.hqwc.cn/news/59597.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PoseFormer:基于视频的2D-to-3D单人姿态估计

3D Human Pose Estimation with Spatial and Temporal Transformers论文解析 摘要1. 简介2. Related Works2.1 2D-to-3D Lifting HPE2.2 GNNs in 3D HPE2.3 Vision Transformers 3. Method3.1 Temporal Transformer Baseline3.2 PoseFormer: Spatial-Temporal TransformerSpati…

Spring Boot通过切面实现方法耗时情况

Spring Boot通过切面实现方法耗时情况 依赖 <dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.9.1</version></dependency>自定义注解 package com.geekmice.springbootself…

【前端 | CSS】aligin-items与aligin-content的区别

align-items 描述 CSS align-items 属性将所有直接子节点上的 align-self 值设置为一个组。align-self 属性设置项目在其包含块中在交叉轴方向上的对齐方式 align-items是针对每一个子项起作用&#xff0c;它的基本单位是每一个子项&#xff0c;在所有情况下都有效果&…

微信生态升级!小绿书来了!

如你所知&#xff0c;微信不只是一个聊天工具。一切从照片开始&#xff0c;你拍了一张照片&#xff0c;你就拥有了自己的相册&#xff0c;在“朋友圈”你可以了解朋友们的生活。如你所见&#xff0c;微信&#xff0c;是一个生活方式。不知不觉间&#xff0c;微信已经走过了 11个…

LeetCode--HOT100题(22)

目录 题目描述&#xff1a;160. 相交链表&#xff08;简单&#xff09;题目接口解题思路代码 PS: 题目描述&#xff1a;160. 相交链表&#xff08;简单&#xff09; 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表…

Spring中Bean的“一生”(生命周期)

文章目录 一、图解二、文字解析总结 一、图解 >注&#xff1a;处于同一行的执行顺序是从左往右 二、文字解析 SpringBean的生命周期总体分为四个阶段&#xff1a;实例化>属性注入>初始化>销毁 Step1 实例化Bean&#xff1a;根据配置文件中Bean的定义&#xff0c;…

MyCat管理及监控——zookeeper及MyCat-web安装

1.MyCat管理 2.MyCat-eye 3.zookeeper安装 第一步&#xff1a;解压 第二部&#xff1a; 切换目录&#xff0c;创建data文件夹 第三步&#xff1a;修改zookeeper配置文件 这样zookeeper安装及配置就完成了 4.MyCat-web安装 注意mycat-web要与zookeeper关联&#xff0c;…

Effective Java笔记(26)请不要使用原生态类型

首先介绍一些术语 。 声明中具有一个或者多个类型参数&#xff08; type parameter &#xff09;的类或者接口&#xff0c;就是泛型&#xff08; generic &#xff09;类或者接口 。 例如&#xff0c;List 接口就只有单个类型参数 E &#xff0c;表示列表的元素类型 。这个接口…

如何识别手机是否有灵动岛(dynamic island)

如何识别手机是否有灵动岛&#xff08;dynamic island&#xff09; 灵动岛是苹果2022年9月推出的iPhone 14 Pro、iPhone 14 Pro Max首次出现&#xff0c;操作系统最低是iOS16.0。带灵动岛的手机在竖屏时顶部工具栏大于等于51像素。 #define isHaveDynamicIsland ({ BOOL isH…

【原创】基于JavaWeb的婚礼策划平台

主要功能介绍&#xff1a;系统基于Java语言开发。整个程序属于B/S架构应用。在开发的时候&#xff0c;将婚礼策划中主要的业务如&#xff1a;婚纱摄影预约以及婚纱租赁等作为主要的目标和研究方向。婚礼策划平台系统从整体结构设计上&#xff0c;由网站前台和系统后台组成。网站…

gSpan算法执行步骤详解示例

目录 1. 问题描述2. gSpan算法步骤2.1 数据预处理2.2 深度递归挖掘频繁子图2.2.1 获取所有的频繁边2.2.2 深度递归挖掘频繁子图 参考文献 1. 问题描述 gSpan 是一款图规则挖掘算法&#xff0c;目标是从现有的图集中挖掘频繁子图。如下图中包含三个图&#xff1a; 其中圆圈为顶…

Explorable Tone Mapping Operators

Abstract 色调映射在高动态范围(HDR)成像中起着至关重要的作用。 它的目的是在有限动态范围的介质中保存HDR图像的视觉信息。 虽然许多工作已经提出从HDR图像中提供色调映射结果&#xff0c;但大多数只能以一种预先设计的方式进行色调映射。 然而&#xff0c;声调映射质量的主…