iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C++设计与声明超详细讲解
  • 761
分享到

C++设计与声明超详细讲解

2024-04-02 19:04:59 761人浏览 薄情痞子
摘要

目录让接口被正确使用不易被误用宁以pass-by-reference-to-const替换pass-by-value必须返回对象时将成员变量声明为private以non-member

让接口被正确使用不易被误用

除非有好的理由,否则应该让你的types的行为与内置types一致,请拿ints做范本

提供行为一致的接口!

阻止误用的办法包括建立新类型,限制类型上的操作,束缚对象值(比如要统计年月日,限制月的大小在1-12),消除客户的资源管理责任(智能指针)

shared_ptr支持定制型删除器,可被用来自动解除互斥

宁以pass-by-reference-to-const替换pass-by-value

值传递要调用copy构造函数,释放时要调用多次析构函数(有副本),费时

const的必要性:引用传递代替值传递时,确保不会对传入的数据做改变

防止被切割:

class Window{
public:
    virtual void display();
}
class WindowWithScrollBars:public Window{
public:
    virtual void display();
}
void show(Window w){
    w.display();
}

当用一个WindowWithScrollBars对象传入show时,因为是值传递,会导致其特化信息被切割,变成了一个Window对象!无法多态了!

应该如下:传进来的窗口是什么类型,w就表现出哪种特性

void show(const Window& w){
    ...
}

说到底,引用是指针实现出来的,引用传递说到底也是传递的指针,如果有一个对象属于内置类型,值传递效率会比引用传递效率高一些。

值传递对于内置类型和STL的迭代器和函数对象来说代价不贵,其他类型还是选用const引用传递好!

必须返回对象时

别妄想返回reference

不是所有情况都是引用传递好

const A& operator*(const A& rhs){
    A result(rhs);//调用构造函数
    return result; 
}

返回了一个result的引用,但result是一个局部变量,离开作用域就被析构了!!!

引用不能返回一个局部对象,否则一败涂地

一个必须返回新对象的函数的做法是:就让他返回一个新对象呗

const A operator*(const A& rhs){
    A result(rhs);//调用构造函数
    return A(rhs); 
}

承受一个operator*构造和析构函数的代价即可

绝对不要返回一个指针或引用指向一个local stack对象(出作用域会被析构),或返回引用指向一个heap-allocated对象(无法保证合理的delete),或返回指针或引用指向一个local static对象而有可能同时需要多个这样的对象(一个指针修改了指向对象的参数后,其他指针指向的参数也被修改了)

将成员变量声明为private

语法一致性:成员变量不是public,用户只能通过public里的相应函数来访问成员变量,用户使用时就都有一致的使用规则(全都要使用小括号等)

使用函数可以对成员变量的处理有更精确的控制,如可以编写const函数实现只读访问,不加const实现读写访问等

封装性,防止成员变量被更改

假如有一个public成员变量,我们最终取消了它,所有使用它的代码都会被破坏,假如有一个protected成员变量,我们最终取消了它,所有使用它的派生类都会被破坏。因此protected其实并不比public更加具有封装性

说到底,选择private就好

以non-member non-friend替换member函数

能够访问private成员变量的函数只有class的member函数加上friend函数,如果要在一个member函数(不只可以访问private数据,也能取用private函数、enums、typedefs等)和一个non-member,non-friend函数做抉择,较好封装性的时后者。因为它并不增加能够访问class内private成分的函数数量

将所有便利函数放在多个头文件内但同属于一个命名空间,用户可以轻松添加这一组便利函数,即可以添加更多的non-member,non-friend函数到此命名空间

参考c++标准程序库,vector、alGorithm等,导入头文件再进行调用,即可完成很多事情

non-member

若所有参数皆需要类型转换,请为此采用non-member函数

class Rational{
public:
    Rational(int numerator=0,int denominator=1);
    int numerator() const;
    int denominator() const;
    const Rational operator* (const Rational& rhs) const;
}
Rational onehalf(1,2);
Rational result=onehalf*2;//很好!
Rational result=2*onehalf;//不行!

原因在于:

result=onehalf.operator*(2);//发生了隐式转换 得益于之前没有将构造函数声明为explicit
result=2.operator*(onehalf);

2没有相应的class,没有operator*成员函数,当然无法执行

结论为:只有当参数被列于参数列内,这个参数才是隐式转换的合格参与者

改变做法为将operator*变成non-member函数,允许编译器在每个实参上执行隐式转换

operator*是否应该成为class的一个friend函数呢?否定的,因为operator*完全可以借用Rational的public接口完成任务,这告诉我们:member函数的反面是non-member,而不是friend

如果你需要为某个函数的所有参数(包括this指针所指的那个隐喻参数)进行类型转换,那么这个函数必须是non-member

考虑写出一个不抛出异常的swap函数

当做swap时,如果交换内部的指针,效率就高了呀

以指针指向一个对象,内含真正的数据,即pimpl手法(pointer to implementation)

class WidgetImpl{
public:
    ...
private:
    int a,b,c;
}
class Widget{
public:
    void swap(Wideget& other){
        using std::swap;//必要的,在找不到class里的swap函数调用此函数
        swap(p,other.p);
    }
private:
    WidgetImpl* p;
}
//修订后的std::swap特化版本
namespace std{
    template<>
    void swap<Widget>(Widget& a,Widget& b)
    {
        a.swap(b);//调用a的swap成员函数
    }
}

这种方法和STL有一致性,因为STL也提供有public的成员函数和std::swap的特化版本

如果swap的默认版本的效率你可以接受,那不需要做任何事

如果swap的默认版本实现效率不足:

1、提供一个public swap成员函数,让它高效的置换两个对象(pimpl)

2、在class的命名空间内提供一个non-member swap,并用它调用上诉swap成员函数。

3、如果正在编写一个class,为class特化std::swap,并用它调用你的swap成员函数。

到此这篇关于C++设计与声明超详细讲解的文章就介绍到这了,更多相关C++设计与声明内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: C++设计与声明超详细讲解

本文链接: https://www.lsjlt.com/news/168348.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C++设计与声明超详细讲解
    目录让接口被正确使用不易被误用宁以pass-by-reference-to-const替换pass-by-value必须返回对象时将成员变量声明为private以non-member...
    99+
    2024-04-02
  • SpringCloud超详细讲解Feign声明式服务调用
    目录入门案例@FeignClient注解详解Feign Client的配置Feign请求添加headers负载均衡 (Ribbon)容错机制Hystrix支持Sentinel支持Fe...
    99+
    2024-04-02
  • C++BoostUuid超详细讲解
    目录一、说明二、Boost.Uuid库示例和代码一、说明 Boost.Uuid 为 UUID 提供生成器。 UUID 是不依赖于中央协调实例的通用唯一标识符。例如,没有数据库存储所有...
    99+
    2022-12-08
    C++ Boost Uuid C++ Uuid标识符
  • C++BoostUtility超详细讲解
    目录一、说明二、Boost.Utility库示例和代码一、说明 Boost.Utility 库是杂项、有用的类和函数的集合,它们太小而无法在独立库中维护。虽然实用程序很小并且可以快速...
    99+
    2022-12-08
    C++ Boost Utility C++ Utility库
  • C语言函数声明以及函数原型超详细讲解示例
    C语言代码由上到下依次执行,原则上函数定义要出现在函数调用之前,否则就会报错。但在实际开发中,经常会在函数定义之前使用它们,这个时候就需要提前声明。 所谓声明(Declaration...
    99+
    2023-02-11
    C语言函数声明 C语言函数原型 C语言函数声明与函数原型
  • C++超详细讲解树与二叉树
    目录树树的定义树的名词解释树的表示树的存储结构二叉树的概念及结构二叉树的概念二叉树的性质二叉树的存储结构顺序存储结构链式存储结构树 树的定义 Q:什么是树 A:树是一种 非线性 的数...
    99+
    2024-04-02
  • Netty与NIO超详细讲解
    目录Linux下的五种I/O模型阻塞IO的流程IO复用信号驱动I/O异步IONIOI0多路复用NIO核心组件使用Java原生API实现NIO操作Redis为什么支持高并发Linux下...
    99+
    2022-11-13
    Netty NIO模型 Netty NIO原理
  • C++ Boost Assign超详细讲解
    目录说明Exercise说明 Boost.Assign Boost.Assign 库提供了帮助函数来初始化容器或向容器添加元素。如果需要将许多元素存储在一个容器中,这些函数尤其有用。...
    99+
    2022-12-09
    C++ Boost Assign C++ Assign库
  • C++超详细讲解友元与内部类
    目录一.友元1.友元函数(1)引入原因(2)友元函数作用(3)友元函数特征2.友元类(1)解释(2)友元类特征二.内部类(不常用)1.概念2.特性 一.友元 友元分为: 友...
    99+
    2024-04-02
  • C++超详细讲解泛型
    目录1.了解泛型编程2.函数模板2.1简单示例2.2多个模板参数2.3模板实例化2.4模板和普通函数同时存在2.5函数模板不支持定义和声明分离3.类模板3.1简单示例3.2成员函数声...
    99+
    2024-04-02
  • C++ 超详细讲解stack与queue的使用
    目录stack介绍和使用模拟实现stack的使用例题最小栈栈的弹出压入序列逆波兰表达式求值queue模拟实现容器适配器deque简介priority_queue优先级队列priori...
    99+
    2024-04-02
  • C++超详细讲解auto与nullptr的使用
    目录一. auto关键字1. auto介绍2. 使用规则3. auto不能推导的场景二. 基于范围的for循环(C++11)1. 范围for的语法2. 范围for的使用条件三. 指针...
    99+
    2024-04-02
  • C++单例设计模式详细讲解
    目录特殊类设计只能在堆上创建对象的类请设计一个类只能在栈上创建对象请设计一个类不能被拷贝请设计一个类不能被继承请设计一个类只能创建一个对象(单例模式)懒汉模式和饿汉模式的对比特殊类设...
    99+
    2024-04-02
  • Java 超详细讲解设计模式之原型模式讲解
    目录传统方式原型模式基本介绍原型模式在spring框架中源码分析深入讨论-浅讨论和深拷贝原型模式的注意事项和细节传统方式 克隆羊问题 现在有一只羊 tom,姓名为: tom,年龄为:...
    99+
    2024-04-02
  • C++BoostPropertyTree示例超详细讲解
    目录一、提要二、应用示例练习一、提要 借助类 boost::property_tree::ptree,Boost.PropertyTree 提供了一个树结构来存储键/值对。树形结构意...
    99+
    2022-11-13
    C++ Boost PropertyTree C++ Boost PropertyTree示例
  • C++BoostOptional示例超详细讲解
    目录一、概述二、Boost.Optional一、概述 数据结构类似于容器,因为它们可以存储一个或多个元素。但是,它们与容器不同,因为它们不支持容器通常支持的操作。例如,使用本部分介绍...
    99+
    2022-11-13
    C++ Boost Optional C++ Boost Optional示例
  • C++BoostVariant示例超详细讲解
    目录一、提要二、示例一、提要         Boost.Variant 提供了一个类似于 unio&...
    99+
    2022-11-13
    C++ Boost Variant C++ Boost Variant示例
  • C++超详细讲解标准库
    目录一、有趣的重载二、C++ 标准库三、小结一、有趣的重载 操作符 << 的原生意义是按位左移,例:1 <<2; 其意义是将整数 1 按位左移2位,即:000...
    99+
    2024-04-02
  • C++超详细讲解稀疏矩阵
    目录稀疏矩阵矩阵与稀疏矩阵的定义稀疏矩阵的转置详细思路思路一思路二稀疏矩阵的乘法详细思路稀疏矩阵 矩阵与稀疏矩阵的定义 Q:什么是矩阵 A:数学上,一个矩阵由 m 行 n 列的元素组...
    99+
    2024-04-02
  • AndroidLayerDrawable超详细讲解
    目录1. 前言2. 实例1. 前言 Android LayerDrawble 包含一个Drawable数组,系统将会按照这些Drawable对象的数组顺序来绘制他们,索引最大的 Dr...
    99+
    2022-11-13
    Android LayerDrawable Android LayerDrawable原理
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作