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

相关文章

Java8需要知道的4个函数式接口简单教程

《Java8需要知道的4个函数式接口简单教程》:本文主要介绍Java8中引入的函数式接口,包括Consumer、Supplier、Predicate和Function,以及它们的用法和特点,文中... 目录什么是函数是接口?Consumer接口定义核心特点注意事项常见用法1.基本用法2.结合andThen链

在Dockerfile中copy和add的区别及说明

《在Dockerfile中copy和add的区别及说明》COPY和ADD都是Dockerfile中用于文件复制的命令,但COPY仅用于本地文件或目录的复制,不支持自动解压缩;而ADD除了复制本地文件或... 目录在dockerfile中,copy 和 add有什么区别?COPY 命令ADD 命令总结在Doc

MySQL 日期时间格式化函数 DATE_FORMAT() 的使用示例详解

《MySQL日期时间格式化函数DATE_FORMAT()的使用示例详解》`DATE_FORMAT()`是MySQL中用于格式化日期时间的函数,本文详细介绍了其语法、格式化字符串的含义以及常见日期... 目录一、DATE_FORMAT()语法二、格式化字符串详解三、常见日期时间格式组合四、业务场景五、总结一、

C++实现回文串判断的两种高效方法

《C++实现回文串判断的两种高效方法》文章介绍了两种判断回文串的方法:解法一通过创建新字符串来处理,解法二在原字符串上直接筛选判断,两种方法都使用了双指针法,文中通过代码示例讲解的非常详细,需要的朋友... 目录一、问题描述示例二、解法一:将字母数字连接到新的 string思路代码实现代码解释复杂度分析三、

golang panic 函数用法示例详解

《golangpanic函数用法示例详解》在Go语言中,panic用于触发不可恢复的错误,终止函数执行并逐层向上触发defer,最终若未被recover捕获,程序会崩溃,recover用于在def... 目录1. panic 的作用2. 基本用法3. recover 的使用规则4. 错误处理建议5. 常见错

解读Pandas和Polars的区别及说明

《解读Pandas和Polars的区别及说明》Pandas和Polars是Python中用于数据处理的两个库,Pandas适用于中小规模数据的快速原型开发和复杂数据操作,而Polars则专注于高效数据... 目录Pandas vs Polars 对比表使用场景对比Pandas 的使用场景Polars 的使用

C++一个数组赋值给另一个数组方式

《C++一个数组赋值给另一个数组方式》文章介绍了三种在C++中将一个数组赋值给另一个数组的方法:使用循环逐个元素赋值、使用标准库函数std::copy或std::memcpy以及使用标准库容器,每种方... 目录C++一个数组赋值给另一个数组循环遍历赋值使用标准库中的函数 std::copy 或 std::

C++使用栈实现括号匹配的代码详解

《C++使用栈实现括号匹配的代码详解》在编程中,括号匹配是一个常见问题,尤其是在处理数学表达式、编译器解析等任务时,栈是一种非常适合处理此类问题的数据结构,能够精确地管理括号的匹配问题,本文将通过C+... 目录引言问题描述代码讲解代码解析栈的状态表示测试总结引言在编程中,括号匹配是一个常见问题,尤其是在

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

C++初始化数组的几种常见方法(简单易懂)

《C++初始化数组的几种常见方法(简单易懂)》本文介绍了C++中数组的初始化方法,包括一维数组和二维数组的初始化,以及用new动态初始化数组,在C++11及以上版本中,还提供了使用std::array... 目录1、初始化一维数组1.1、使用列表初始化(推荐方式)1.2、初始化部分列表1.3、使用std::