C++逻辑设计——函数设计之函数接口说明

2023-10-12 10:20

本文主要是介绍C++逻辑设计——函数设计之函数接口说明,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在C++中指定函数接口时,一些必须要解决的问题有:

(1) 运算符函数还是非运算符函数?
(2) 自由运算符还是成员运算符?
(3) 虚函数还是非虚函数?
(4) 纯虚成员函数还是非纯虚成员函数?
(5) 静态成员函数还是非静态成员函数?
(6) 常量成员函数还是非常量成员函数?
(7) public、protected 还是 private 成员函数?
(8) 通过值、引用还是指针返回?
(9) 返回常量还是非常量?
(10) 参数是可选的还是必需的?
(11) 通过值、引用还是指针传递参数?
(12) 将参数作为常量传递还是非常量传递?

有俩个组织问题,尽管不属逻辑接口的一部分,但是也必需解决:

(13) 友元函数还是非友元函数?
(14) 内联函数还是非内联函数?

(1) 运算符函数还是非运算符函数

除了编译器生成的运算符(例如赋值) 之外,将一个函数函数设计成一个运算符函数的唯一理由是方便客户端的标记。

一个成员函数调用一个运算符产生的函数调用解析,和在文件作用域中函数调用的解析是一样的。

1) 可读性(超过易用性) 应该是运算符重载的主要原因。
2) 一个重载运算符的语义对于用户来应该是自然、明显和直观的。
3) 预定义C++ 运算符之后,模拟用户自定义运算符的语法性质,可以避免意外并且使它们的使用具有更高的可预测性。

在C++中,每个表达式都有一个值。有俩种基本类型的值,分别称为左值 (lvalue) 和右值 (rvalue)。左值是可以获得其地址的值,如果一个左值可以在赋值语句的“左边”,就被认为是一个可修改的左值,否则被认为是一个不可修改的左值。

右值不能被赋值,也不能获得它的地址。最简单的左值表达式是变量标识符,除非这个变量被声明为常量,否则该变量就是一个可修改的左值。

某些运算符,例如,赋值运算符 (=) 和它的变化形式(+=、-=、*=、/=、^=、&=、| =、~=、%=、>>=、<<=)、前置增量(++X)和前置减量,使用基本类型时都返回可修改的左值,这些运算符总是返回一个指向修改后参数的可写引用。例如,对于基本类型double(如果作为一个C++类实现),这些运算符假设的定义如下代码所示:

class double{//...
public:double(){}double(int);doubel(const double&);~double(){}double& operator=(const double& d);double& operator+=(const double& d);double& operator-=(const double& d);double& operator*=(const double& d);double& operator/=(const double& d);double& operator++();  //pre-increment ++xdouble& operator++();  //pre-decrement --xdouble operator++(int); //post-increment x++double operator--(int); //post-decrement x--double *operator&();  //unary address operatorconst double *operator&() const;  //
};double operator+(const double& d);
double operator-(const double& d);int operator!(const double& d);int operator&&(const double& left, const double& right);
int operator||(const double& left, const double& right);double operator+(const double& left, const double& right);
double operator-(const double& left, const double& right);
double operator*(const double& left, const double& right);
double operator/(const double& left, const double& right);double operator==(const double& left, const double& right);
double operator!=(const double& left, const double& right);
double operator<(const double& left, const double& right);
double operator<=(const double& left, const double& right);
double operator>(const double& left, const double& right);
double operator>=(const double& left, const double& right);

由于没有合适的左值返回,所以上述代码所示的其他运算符返回一个右值。

至于对称的二元运算符(例如,+和*),所返回的值既不是左边的参数也不是右边的参数,而是一个派生于这俩个值的新值,因此必须通过值来返回。

等式(==、!=)和关系运算符(<,<=,>,>=)总是返回一个int类型的右值,不是0就是1,显然,没有输入参数适合在这里返回。

后置递增和后置递减运算符是比较特别,只有它们可以修改对象却没有返回适当的左值:

double double::operator++(int)
{double tmp= *this;++ *this;return tmp;
}double double::operator--(int)
{double tmp= *this;-- *this;return tmp;
}

这里写图片描述

上图总结了应用于基本类型时大多数C++运算符的声明。值得注意的是,没有修改其参数的一元运算不是基本成员。例如,对一个诸如 “ostream”的用户定义类型,一元运算符 “!”,即使没有给这种类型定义 “!” 运算符:

#include"iostream.h"
void g(ostream &out)
{if(!out){cerr<<"output stream is bad"<<endl;return;}//...
}

代码工作正常,因为ostream知道如何将自己隐式地转换为定义了“!”运算符的基本类型(void *) (这里有点搞不明白???希望有大神可以指点下)

(3) 虚函数还是非虚函数

动态绑定能使通过一个基类访问的成员函数由实际对象的子类型来决定,一个函数必须声明为virtual才能被动态绑定。

首先简单介绍下动态绑定和静态绑定:

=================================================================================================
静态绑定:编译时绑定,通过对象调用
动态绑定:运行时绑定,通过地址实现

C++的多态性:
1) 静态多态性:函数多态性—函数重载、模板多态性—C++模板(类模板、函数模板)
2) 动态多态性:虚函数(只有用地址才能实现动态多态性)

只有采用 “指针->函数()”“引用变量.函数()” 的方式调用C++类中的虚函数才会执行动态绑定。对于C++ 中的非虚函数,因为其不具备动态绑定的特征,所以不管采用什么样的方式,都不会执行动态绑定。

C++语言成员函数的调用和绑定方式总结:

这里写图片描述

注:被引用对象所属类指针或引用指向的对象<

这篇关于C++逻辑设计——函数设计之函数接口说明的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/195186

相关文章

springboot下载接口限速功能实现

《springboot下载接口限速功能实现》通过Redis统计并发数动态调整每个用户带宽,核心逻辑为每秒读取并发送限定数据量,防止单用户占用过多资源,确保整体下载均衡且高效,本文给大家介绍spring... 目录 一、整体目标 二、涉及的主要类/方法✅ 三、核心流程图解(简化) 四、关键代码详解1️⃣ 设置

spring中的ImportSelector接口示例详解

《spring中的ImportSelector接口示例详解》Spring的ImportSelector接口用于动态选择配置类,实现条件化和模块化配置,关键方法selectImports根据注解信息返回... 目录一、核心作用二、关键方法三、扩展功能四、使用示例五、工作原理六、应用场景七、自定义实现Impor

Windows下C++使用SQLitede的操作过程

《Windows下C++使用SQLitede的操作过程》本文介绍了Windows下C++使用SQLite的安装配置、CppSQLite库封装优势、核心功能(如数据库连接、事务管理)、跨平台支持及性能优... 目录Windows下C++使用SQLite1、安装2、代码示例CppSQLite:C++轻松操作SQ

C++中RAII资源获取即初始化

《C++中RAII资源获取即初始化》RAII通过构造/析构自动管理资源生命周期,确保安全释放,本文就来介绍一下C++中的RAII技术及其应用,具有一定的参考价值,感兴趣的可以了解一下... 目录一、核心原理与机制二、标准库中的RAII实现三、自定义RAII类设计原则四、常见应用场景1. 内存管理2. 文件操

C++中零拷贝的多种实现方式

《C++中零拷贝的多种实现方式》本文主要介绍了C++中零拷贝的实现示例,旨在在减少数据在内存中的不必要复制,从而提高程序性能、降低内存使用并减少CPU消耗,零拷贝技术通过多种方式实现,下面就来了解一下... 目录一、C++中零拷贝技术的核心概念二、std::string_view 简介三、std::stri

C++高效内存池实现减少动态分配开销的解决方案

《C++高效内存池实现减少动态分配开销的解决方案》C++动态内存分配存在系统调用开销、碎片化和锁竞争等性能问题,内存池通过预分配、分块管理和缓存复用解决这些问题,下面就来了解一下... 目录一、C++内存分配的性能挑战二、内存池技术的核心原理三、主流内存池实现:TCMalloc与Jemalloc1. TCM

Before和BeforeClass的区别及说明

《Before和BeforeClass的区别及说明》:本文主要介绍Before和BeforeClass的区别及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Before和BeforeClass的区别一个简单的例子当运行这个测试类时总结Before和Befor

Python中help()和dir()函数的使用

《Python中help()和dir()函数的使用》我们经常需要查看某个对象(如模块、类、函数等)的属性和方法,Python提供了两个内置函数help()和dir(),它们可以帮助我们快速了解代... 目录1. 引言2. help() 函数2.1 作用2.2 使用方法2.3 示例(1) 查看内置函数的帮助(

Python pip下载包及所有依赖到指定文件夹的步骤说明

《Pythonpip下载包及所有依赖到指定文件夹的步骤说明》为了方便开发和部署,我们常常需要将Python项目所依赖的第三方包导出到本地文件夹中,:本文主要介绍Pythonpip下载包及所有依... 目录步骤说明命令格式示例参数说明离线安装方法注意事项总结要使用pip下载包及其所有依赖到指定文件夹,请按照以

C++ 函数 strftime 和时间格式示例详解

《C++函数strftime和时间格式示例详解》strftime是C/C++标准库中用于格式化日期和时间的函数,定义在ctime头文件中,它将tm结构体中的时间信息转换为指定格式的字符串,是处理... 目录C++ 函数 strftipythonme 详解一、函数原型二、功能描述三、格式字符串说明四、返回值五