C++ 读书笔记 Effective C++(三)

读书笔记:《Effective Modern C++(C++14)》 使用RAII(“Resource Acquisition Is Initialization,资源获得即初始化)包装thread,在析构时进行join。和闭包类存在于编译期,闭包存在于运行时。 阅读详情
public继承意味着is-a;virtual函数意味着接口必须被继承 none-virtual函数意味着接口和实现都必须被继承。

32.确定你的public继承塑模出is-a关系

       “public继承”意味is-a.适用于base classes身上的每一件事情一定也适用于derived classes身上,因为每一个derived class对象也都是一个base class对象
       两个问题:1.“所有鸟多会飞,企鹅是鸟,但是企鹅不会飞”.  2.”class Square 应该以public形式继承class Retangle吗?”
        对于第一个问题:“你应该宁可采取”在编译期拒绝企鹅飞行“的设计,而不是”只在运行期才能侦测它们”的设计。
        对于第二个问题:”本例的根本困难是,某些可施行于矩形身上的事情却不可以施行于正方形身上(宽度总是应该和高度一样)。但是       public 继承主张,能够施行于base class对象身上的每件事情,也可以施行于derived class对象身上。在正方形和矩形例子中,那样的主张无法保持,所以以public继承塑模它们之间的关系并不正确."

     “public继承”意味着is-a。适用于base classes身上的每一件事情一定也适用于derived classes身上,因为每一个derived classes对象也都是一个base classes对象。

33.避免遮掩继承而来的名称
 class Base
{
public:
   
 virtual void mf1() = 0;
   
 virtual void mf1(int);
   
 virtual void mf2();
   
 void mf3();
   
 void mf3(double);
private:
   
 int x;
};


class Derived :public Base
{
public:
    virtual void mf1();
   
 void mf3();
   
 void mf4();
};

void Test()
{
   
 Derived d;
   
 int x = 1;
   
    d.
mf1();
   
 //d.mf1(2); //错误!因为Derived::mf1遮掩了Base::mf1
    d.
mf2();    //调用的是Base::mf2
    d.
mf3();    //调用的是Base::mf3
   
 //d.mf3(x);   //错误!因为Derived::mf1遮掩了Base::mf3
    d.
mf4();    //调用的是Derived::mf4
   
}
   即使 base classes和derived classes内的函数有不同的参数类型也适用,而且不论函数是virtual和non-virtual一体适用。这些行为背后的基本理由是为了防止你在程序或应用框架内建立新的derived calss时附带地从疏远地base classes继承重载函数。不幸地是你通常会想继承重载函数。实际上如果你正在使用public继承而又不继承那些重载函数,就是违反base和derived classes之间地is-a关系。

class Base
{
public:
   
 virtual void mf1() = 0;
   
 virtual void mf1(int);
   
 virtual void mf2();
   
 void mf3();
   
 void mf3(double);
private:
   
 int x;
};


class Derived :public Base
{
public:
   
 using Base::mf1;
   
 using Base::mf3;
   
   
 virtual void mf1();
   
 void mf3();
   
 void mf4();
};

void Test()
{
   
 Derived d;
   
 int x = 1;
   
    d.
mf1();    //调用的是Derived::mf1
    d.
mf1(2);   //调用的是Base::mf1
    d.
mf2();    //调用的是Base::mf2
    d.
mf3();    //调用的是Base::mf3
    d.
mf3(x);   //调用Base::mf3
    d.
mf4();    //调用的是Derived::mf4
   
}
注意:1.base class内的public名称在publicly derived class内也应该是public.
     2.使用using声明会令继承而来的某给定名称之所有同名函数在derived classes中都可见。可以使用一个简单的转交函数(forward function),例如我们想在Derived内只使用mf1的午参数版本可以这样来做:

   
 virtual void mf1()
    {
       
 Base::mf1();
    }

总结:
 derived classes内的名称会遮掩base classes内的名称。在public 继承下从来没有人希望如此。
 为了让被遮掩的名称再现天日,可使用using声明式或转交函数(forwarding function)。

34.区分接口继承和实现继承

纯虚函数有两个最突出的特性:它们必须被任何“继承了它们”的具象class重新声明,而且它们在抽象class中通常没有定义。即:声明一个纯虚函数的目的是让derived classes只继承函数接口。
注:我们可以为纯虚数提供定义,但调用它的唯一途径是”调用时明确指出其class名称”.不过一般而言这项性质用途有限。

class IShape
{
private:
   
 int objID;
public:
   
 virtual void draw() const = 0;
   
 virtual void error(const std::string& msg);
   
 int objectID() const {return objID;}
};
void IShape::draw() const
{
}
class Retangle:public IShape
{
public:
   
 virtual void draw() const;
   
 virtual void error(const std::string& msg);
};
void Retangle::draw() const
{
   
 //defalut 
}
void Retangle::error(const std::string& msg)
{
}

class Ellipse:public IShape
{
public:
    Ellipse();
   
 virtual void draw() const {}
   
 virtual void error(const std::string& msg){}
   
};


void Test()
{
    IShape* ps1 = new Retangle;
    ps1->
draw();
   
 IShape *ps2 = new Ellipse;
    ps2->
draw();
    ps1->
IShape::draw();    //调用Shape::draw
    ps2->
IShape::draw();    //调用Shape::draw
}

        与纯虚函数有点不同,对于虚函数派生类继承其函数接口,但虚函数会提供一份代码实现,派生类可覆盖它。声明虚函数的目的,是让派生类继承该函数的接口和缺省实现。
        如上面的error接口,每个class都必须支持一个“当遇上错误时可调用”的函数,但每个class可自由处理错误。如果某个class不行针对错误做出任何特殊的行为,它可以退回到Shape class提供的缺省错误处理。也就是说Shape::error的声明式告诉派生类的设计者,“你必须支持一个error函数,但如果你不想自己写一个,可以使用Shape class提供的缺省版本。
         声明non-virtual函数的目的是为了令derived classes继承函数的接口以及一份强制实现。如果成员函数有一个non-virtual函数,意味者它并不打算在derived classes中有不同的行为。实际上一个non-virtual成员函数所变现的不变性凌驾其特异性。

总结:
接口继承和实现继承不同。在public继承之下,derived classes总是继承base class的接口。 
pure virtual函数只具体指定接口继承。
简朴(非纯)impure vritual 函数具体指定接口继承及缺省实现继承。
non-virtual函数具体指定接口继承以及强制实现继承。

35.考虑virtual函数以外的其它选择

令客户端通过public non-virtual成员函数间接调用private virtual函数,称为non-virtual interface手法,它也式所谓的Template Method设计模式的一个独特表现形式。把这个non-virtual函数称为virtual函数的外覆盖器。

#include <iostream>
using namespace std;

class GameCharacter
{
public:
   
 int healthValue() const            //derived  classes 不重新定义它
    {
       
 //.......                       //做一些事前工作,详下
       
 int reVal = doHealthValue();    //做真正的工作
       
 //......                        //做一些事后工作,详下
       
       
 return reVal;
    }
private:
   
 virtual int doHealthValue() const  //derived classes可重新定义它
    {
       
 //....                          //缺省计算,计算健康指数
    }
};

class EvilBadGuy:public GameCharacter
{
public:
   
 virtual int doHealthValue() const
    {
       
 cout << "EvilBadGuy health value." << endl;
    }
private:
};


void TestGameCharacter()
{
   
 EvilBadGuy obj;
    obj.
healthValue();
}
#endif



古典的Strategy模式
class GameCharacter;
class HealthCalcFunc
{
public:
   
 virtual int calc(const GameCharacter& gc) const{};
};

HealthCalcFunc defaultHealthCalc;
class GameCharacter
{
public:
   
 explicit GameCharacter(HealthCalcFunc* phcf=&defaultHealthCalc):pHealthCalc(phcf)
    {
    }
   
 int healthValue() const
    {
       
 return pHealthCalc->calc(*this);
    }
private:
   
 HealthCalcFunc* pHealthCalc;
};
class EvilBadGuy : public HealthCalcFunc
{
public:
   
 virtual int calc(const GameCharacter& gc) const
    {
       
 cout << "EvilBadGuy health value." << endl;
    }
};

void TestGameCharacter()
{
   
 EvilBadGuy obj;
   
 GameCharacter gc(&obj);
    gc.
healthValue();
}

总结:
virtual函数的替代方案包括NVI(non-virtual interface)手法以及strategy设计模式的多种形式。NVI手法自身是一个特殊形式的Template Method设计模式。
将机能从成员函数移到class外部函数,带来的一个缺点是,非成员函数无法访问class的non-public成员
tr1::function对象的行为就像一般函数指针。这样的对象可接纳”与给定之目标签名式兼容”的所有可调用物。


36.绝不重新定义继承而来的non-virtual函数
  

 #include <iostream>
using namespace std;

class B
{
public:
   
 void mf(){cout << "B class" << endl;}
private:
};

class D:public B
{
public:
   
 void mf(){cout <<"D class" << endl;}
};

void TestInterface()
{
   
 D x;
   
 B* pb = &x;
   
 D *pd = &x;
   
    pb->
mf();  // "B class"
    pd->
mf();  // "D class"
   
}
non-virtual函数B::mf和D::mf都是静态绑定的,这意思是说,由于pb被声明为一个pointer-to-B,通过PB的non-virtual函数永远是B所定义的版本,即使PB指向的一个类型是”B派生之class”的对象。
如果你编写class D并重新定义继承自class B的non-virtual函数mf,D对象很可能展现出精神分裂的不一致行径。
在class内声明一个non-virtual函数会为改class建立一个不变性,凌驾其特异性。

总结:任何情况下都不该重新定义一个继承而来的non-virtual函数。


37.绝不重新定义继承而来的缺省参数值

#include <iostream>
using namespace std;
class B
{
public:
   
 virtual void mf(int count=10){cout << "B::count: " << count << endl;}
private:
};

class D:public B
{
public:
   
 virtual void mf(int count = 20){cout <<"D::count: " << count << endl;}
};

void TestInterface()
{
   
 D x;
   
 B* pb = &x;
   
 D* pd = &x;
   
    pb->
mf();  // “D::count: 10"
    pd->
mf();  // "D::count: 20"
   
}

在上面的例子中,pb和pd都被声明为指针类型,它们都是静态类型。注意,不论它们真正指向什么,它们的都是静态类型,pb的静态类型为 B* ,PB的静态类型为D*.
对象的所谓动态型则是指“目前所指对象的类型”,也就是说,动态类型可以表现一个对象将会有什么行为。pb的动态类型是D*,pd的动态类型是D*。
virtual函数动态绑定,意思是调用一个virtual函数时,究竟调用哪一份函数实现代码,取决于发出调用的安哥对象的类型。注意:virtual函数是动态绑定的,但是缺省参数是静态绑定的。
pb视图调用一个定义于derived class内的virtual函数的同时,却使用base class为它所指定的缺省值。


为了防止这样的情况发生可以使用NVI技术。
class B
{
public:
  
 void mfInterface(int count=10){ mf(count); }
private:
   virtual void mf(int count){cout << "B::count: " << count << endl;}
};

class D:public B
{
public:
    
virtual void mf(int count){cout <<"D::count: " << count << endl;}
};

void TestInterface()
{
   
 D x;
   
 B* pb = &x;
   
 D* pd = &x;
   
    pb->
mfInterface();  // "D::count: 10"
    pd->
mfInterface();  // "D::count: 10"
   
}

由于non-virtual函数应该绝对不被derived classes覆写,整个设计使得mf函数的count缺省值总是为10

总结:绝对不要重新定义一个继承而来的缺省值,因为缺省值都是静态绑定,而virtual函数-你唯一应该覆写的东西是动态绑定。

38.通过复合塑模出has-a或”根据某物实现出”
“public继承”带有is-a的意义。复合也有它自己的意义。实际上他有两个意义。复合意味has-a或is-implemented-in-terms-of(根据某物实现).

总结:复合的意义和public继承完全不同
     在应用域,复合意味着has-a有一个。在实现域,复合意味着is-implemented-in-terms-of(根据某物实现出).


39.明智而审慎的使用private继承
如果classes之间继承关系是private,编译器不会自动将一个derived class对象(例如Student)转换为一个base class对象。 由private base class继承而来的所有成员,在derived class中都会变成private属性,纵使它们在base class中原本是protected或public属性。Private继承意味implemented-in-terms-of(根据某物实现出).

总结:Private继承意味is-implemented-in-terms-of(根据某物实现出)。它通常比复合的级别低。但是当derived class需要访问protected base class的成员,或需要重新定义继承而来的virtual函数时,这么设计是合理的。
              和复合不同,private继承可以造成empty base最优化。这对致力于"对象尺寸最小化"的程序开发者而言,可能很重要。

40.明智而审慎地使用多重继承
使用virtual继承的那些classes所产生的对象往往比使用non-virtual继承的兄弟们体积大,访问virtual base classes的成员变量时,也比访问non-virtual base class的成员变量速度慢。
对使用virtual base class的忠告很简单。第一,非必要不使用virtual classes。平时使用non-virtual继承。第二,如果你必须使用virtual base class尽量避免在其中放置数据。这样一来就不需要担心这些classes身上的初始化(和赋值)所带来的诡异事情了。

总结:多重继承比单一继承复杂。他可能导致新的歧义性,以及对virtual继承的需要。
virtual继承会增加大小、速度、初始化(及赋值)复杂度等等成本。如果virtual base classes不带任何数据,将是最具使用价值的情况。
多重继承的确有正当的用途。其中一个情节涉及"public继承某个Interface class"和”private继承某个协助实现的class“的两相同组合。
Effective C++ 条款01:视 C++ 为一个语言联邦 这篇文章摘要: C++是一个由多个次语言组成的语言联邦,包括C风格过程式编程、面向对象的C++、模板元编程和STL标准库。作者通过《Effective C++》第一条指出,理解这种联邦结构是掌握C++的关键。文章详细解析了这四大次语言的核心特性和适用场景:C语言基础用于系统编程;面向对象特性适合大型架构;模板编程支持泛型和元编程;STL提供了容器和算法的高效实现。不同次语言的编程规则差异很大,混合使用时需要注意风格统一。文章通过嵌入式系统、游戏引擎等实际案例,展示了如何根据不同需求选择合适的次语言组合。理解 阅读详情

相关推荐

七自由度机械臂逆运动学实战:从几何简化到KDL库高效求解

本文深入探讨了七自由度机械臂逆运动学求解的实战方法。针对冗余自由度带来的挑战,文章对比了两种核心方案:一是利用任务约束进行几何简化,快速求解特定任务;二是基于DH参数法配置KDL库,实现通用高效的数值迭代求解。文中结合宇树H1机器人实例,详细阐述了从模型解析、参数提取到代码实现与验证的全流程,并提供了几何法与KDL库的适用场景对比与避坑指南。

weixin_29044713的博客 639

《Effective C++(第三版)》读书笔记

结合《Effective C++(第三版)》书和一些技术博客总结的读书笔记,后续还会更新完善 一.让自己习惯C++ 条款01:视C++为一个语言联邦     为了更好的理解C++,我们将C++分解为四个主要次语言: C。说到底C++仍是以C为基础。区块,语句,预处理器,内置数据类型,数组,指针统统来自C。 Object-Oreinted C++。这一部分是面向对象设计之古典守

liaodong1790的博客 841

安卓游戏存档修改全攻略:以《英雄迷宫冒险》为例(附避坑指南)

本文详细介绍了安卓游戏存档修改的全过程,以《英雄迷宫冒险》为例,涵盖基础认知、工具选择、实战修改及风险控制。通过十六进制编辑和UTF-8编码解析,玩家可以修改金钱、角色属性和物品数量等数据,同时提供了避坑指南和伦理考量,帮助玩家在享受修改乐趣的同时保持游戏体验的平衡。

weixin_29209801的博客 392

Effective C++读书笔记(上)

Effective C++读书笔记(一到三章)

still_wtm的博客 748

【分布式系统学习】CAP原理详解

概述:互联网最重要任务莫过于海量数据处理,即大规模分布式系统,分布式是互联网的核心技术!!!如上所述,分布式系统是无法同时满足CAP三个特性的。1.Atomicity(原子性)一个事务中的所有操作,要么全部完成,要么全部不完成,不会在中间某个环节结束。事务在执行过程中发生错误,会被回滚到事务开始前的状态,就像这个事务从来没有执行过一样。2.Consistency(一致性)在事务开始之前和事务结束以后,数据库的完整性没有被破坏。3.Isolation(隔离性)

大龄烤红薯的博客 5024

Ubuntu新手必看:3种方法快速查看和编辑JSON文件(附jq安装指南)

本文为Ubuntu新手详细介绍了三种查看和编辑JSON文件的核心方法:命令行利器jq、灵活脚本Python以及直观的图形化编辑器(如VS Code)。文章重点解析了jq的安装与核心用法,并对比了各方案的优缺点,帮助用户根据快速查询、复杂处理或直观编辑等不同场景,选择最合适的工具,从而高效处理JSON数据。

weixin_29229989的博客 416

Effective C++(第三版)读书笔记

Effective C++(第三版)读书笔记 文章目录Effective C++(第三版)读书笔记1. 让自己习惯C++01.视C++为一个语言城邦02. 尽量以const, enum, inline 替换 #define03. 尽可能使用const04. 确定对象被使用前已经被初始化2. 构造、析构、赋值运算05. 了解C++默默编写并调用哪些函数06. 若不想使用编译器自动生成的函数,就该明确...

Luven777的博客 392

单目标跟踪算法及其复现过程---SiamFC(一)

在test.py文件中,就是利用训练出来的模型进行测试,需要更改预训练模型的路径,测试集的路径,以OTB100为例,最后输出的是对每一帧目标位置的坐标点。代码如下:首先需要下载got10k官方库,只需要在终端输入(注意:在终端安装各种库的时候不能使用网络代理),在环境已经配置到的情况下,只需要该其中的路径和就可以运行。这个系列博客仅为了记录各目标跟踪算法的复现(大多为跑通大佬们实现的代码),包括其中出现的很多问题和错误,学到的新知识等等。解决,而且只使用在线的方法,限制了他们可以学习的模型的丰富性。

weixin_58244117的博客 4762

【读书笔记】Effective C++-1 让自己习惯C++(之一)

Effective C++读书笔记 --By Nathan.Yu 2007-11-10-- 1 让自己习惯C++ 条款01:视C++为一个语言联邦 C++最初的名称是:C with Classes 今天的C++是:多重泛型编程语言(multiparadigm programming language),同时支持过程形式(procedural)、面向对象形式(object-orie

@塘外人 882

Vivado ILA抓不到低频信号?试试Capture Control模式,保姆级配置教程(附PWM调试实例)

本文详细解析了Vivado ILA的Capture Control模式在低频信号捕获中的应用,特别针对PWM调试等场景提供保姆级配置教程。通过条件采样和时间拉伸技术,有效解决传统ILA采样在低频信号调试中的存储深度不足、关键信号丢失等问题,并附赠呼吸灯PWM的完整调试实例,帮助FPGA开发者提升调试效率。

weixin_42549451的博客 350

​​手把手教你学PCIE--ATU 的 Bar 匹配模式与地址匹配模式详解​

摘要: ATU(地址转换单元)提供两种地址匹配模式:Bar匹配模式基于PCI设备的BAR寄存器自动映射虚拟地址(只需配置物理基址),适用于标准PCI设备DMA;地址匹配模式需显式配置虚拟与物理地址范围,适合自定义映射场景。核心区别在于匹配依据(BAR自动推导vs人工定义),Bar模式简化配置,地址模式更灵活。

MHD0815的博客 380

【读书笔记】Effective C++(01)让自己习惯C++

Effective C++ 读书笔记

LogM的博客 211

【WRF-Urban】Registry.EM_COMMON文件概述及urban有关变量

Registry.EM_COMMON文件概述及urban有关变量

WW、forever的博客 1594

【读书笔记】Effective C++-1 让自己习惯C++(之三)

Effective C++读书笔记 --By Nathan.Yu 2007-11-12-- 1 让自己习惯C++(三) 条款04:确定对象被使用前已先被初始化 读取未初始化的值会导致不明确的行为。 最佳的处理方法:永远在使用对象之前先将它初始化。        对内置类型:手工初始化。        对自定义类型:确保每个构造函数都将对象的每一个成员初始化。   别混淆了赋值

@塘外人 691

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

读书笔记-Effective C++

页数:47 条款一: 把C++视为一种联邦语言,因为支持,过程,面向对象,函数,泛型,元编程。 C语言的次语言,有C,Object-Oriented C++。这部分也就是C with Classes;Template C++(泛型编程,一般经验较少);STL 条款二:尽量用const,enum,inline替换define 要是出错,编译器只会定位define替换的东西,不方便找问题。用

baidu_34674626的博客 606

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

《Effective C++》读书笔记(一):让自己习惯C++(条款01~04)

读《Effective C++》第一章:让自己习惯C++ 而写的总结笔记,从条款01到条款04.

wjmhlh的博客 504

【读书笔记】Effective C++(05)实现

Effective C++ 读书笔记

LogM的博客 168

Effective C++(2)读书笔记

(1)为内置对象手工初始化,因为C++不保证一定会初始化它们 (2)为免除“跨编译单元之初始化次序”问题,用local static 对象替换non-local static对象         non-local static对象初始化次序无法确定,如果在未初始化以前调用就会产生大问题         extern FileSyatem tfs;         替换为        

rhythmhui1的专栏 431

《Effective C++》读书笔记第一章——让自己习惯C++(Accustoming Yourself to C++)

条款01:视C++为一个语言联邦 (View C++ as a federation of languages.) 与C++相关的四个特征: C. 说到底C++还是以C为基础。区块(blocks)、语句(statements)、预处理器(preprocessor)、内置数据类型(built-in data types)、数组(arrays)、指针(pointers)等统统来自C。然而C语言拥...

哈哈哈哈嘿嘿嘿 272

Effective C++ 读书笔记 (1.让自己习惯C++)

条款一: 视C++为一个语言联邦 将C++视为一个语言联邦,而非单一的语言,为了理解C++,必须认识四个主要的次语言: C Object-Oriented C++ (相当于是面向对象的C++) Templata C++ (C++泛型编程) STL C++并不是一个带有一组守则的一体语言;它是从四个次语言组成的联邦政府,每个次语言都有自己的规约。 C++高效编程守则视状况而变...

weixin_43133795的博客 167

effective c++_Effective C++ 读书笔记

作者:maxkibble链接:https://www.jianshu.com/p/67d2b4e2d417手头上有一本 Scott Meyes 的 Effective C++(3rd Edition)https://www.amazon.com/gp/product/0321334876,虽然中文的出版时间是感人的2011年(也就是说C++11的那些新特性都没讨论了),但看网上的一些评论...

weixin_39754831的博客 104

【读书笔记】Effective C++-1 让自己习惯C++(之二)

Effective C++读书笔记 --By Nathan.Yu 2007-11-11-- 1 让自己习惯C++(二) 条款03:尽可能使用const const允许你指定一个语义约束(也就是指定一个“不该被改动”的对象),而编译器会强制实施这项约束。   const的用处:修饰global或namespace作用域中的常量;或修饰文件、函数、或区块作用域中被声明为static的对象;

@塘外人 744

C++ 读书笔记 Effective C++(二)

Effective-C++读书笔记

zzbjut 2467

Effective C++(读书笔记)

Effective C++ 这本书共有九个章节55条建议,目录如下: 一. 让自己习惯C++       01.视C++为一个语言联邦       02.尽量以const, enum, inline, 替换#define       03.尽可能使用const       04.确定对象被使用前已被初始化 二. 构造/析构/赋值运算       05.了解C++默认编写并调用哪些函数...

前路漫漫的博客 490

【读书笔记】Effective C++(04)设计与声明

Effective C++ 读书笔记

LogM的博客 182

读书笔记:《More Effective C++》

C++异常处理,栈展开机制:

每一个不曾起舞的日子,都是对人生的辜负。 539
上一篇: C++ 读书笔记 Effective C++(二)
下一篇: 存储管理的页面置换算法
张哲BJUT
博客等级 码龄15年 151粉丝 111原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值