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

相关文章

go中空接口的具体使用

《go中空接口的具体使用》空接口是一种特殊的接口类型,它不包含任何方法,本文主要介绍了go中空接口的具体使用,具有一定的参考价值,感兴趣的可以了解一下... 目录接口-空接口1. 什么是空接口?2. 如何使用空接口?第一,第二,第三,3. 空接口几个要注意的坑坑1:坑2:坑3:接口-空接口1. 什么是空接

Tomcat版本与Java版本的关系及说明

《Tomcat版本与Java版本的关系及说明》:本文主要介绍Tomcat版本与Java版本的关系及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Tomcat版本与Java版本的关系Tomcat历史版本对应的Java版本Tomcat支持哪些版本的pythonJ

C++ 中的 if-constexpr语法和作用

《C++中的if-constexpr语法和作用》if-constexpr语法是C++17引入的新语法特性,也被称为常量if表达式或静态if(staticif),:本文主要介绍C++中的if-c... 目录1 if-constexpr 语法1.1 基本语法1.2 扩展说明1.2.1 条件表达式1.2.2 fa

Android Kotlin 高阶函数详解及其在协程中的应用小结

《AndroidKotlin高阶函数详解及其在协程中的应用小结》高阶函数是Kotlin中的一个重要特性,它能够将函数作为一等公民(First-ClassCitizen),使得代码更加简洁、灵活和可... 目录1. 引言2. 什么是高阶函数?3. 高阶函数的基础用法3.1 传递函数作为参数3.2 Lambda

Nginx指令add_header和proxy_set_header的区别及说明

《Nginx指令add_header和proxy_set_header的区别及说明》:本文主要介绍Nginx指令add_header和proxy_set_header的区别及说明,具有很好的参考价... 目录Nginx指令add_header和proxy_set_header区别如何理解反向代理?proxy

C++中::SHCreateDirectoryEx函数使用方法

《C++中::SHCreateDirectoryEx函数使用方法》::SHCreateDirectoryEx用于创建多级目录,类似于mkdir-p命令,本文主要介绍了C++中::SHCreateDir... 目录1. 函数原型与依赖项2. 基本使用示例示例 1:创建单层目录示例 2:创建多级目录3. 关键注

C++从序列容器中删除元素的四种方法

《C++从序列容器中删除元素的四种方法》删除元素的方法在序列容器和关联容器之间是非常不同的,在序列容器中,vector和string是最常用的,但这里也会介绍deque和list以供全面了解,尽管在一... 目录一、简介二、移除给定位置的元素三、移除与某个值相等的元素3.1、序列容器vector、deque

C++常见容器获取头元素的方法大全

《C++常见容器获取头元素的方法大全》在C++编程中,容器是存储和管理数据集合的重要工具,不同的容器提供了不同的接口来访问和操作其中的元素,获取容器的头元素(即第一个元素)是常见的操作之一,本文将详细... 目录一、std::vector二、std::list三、std::deque四、std::forwa

C++字符串提取和分割的多种方法

《C++字符串提取和分割的多种方法》在C++编程中,字符串处理是一个常见的任务,尤其是在需要从字符串中提取特定数据时,本文将详细探讨如何使用C++标准库中的工具来提取和分割字符串,并分析不同方法的适用... 目录1. 字符串提取的基本方法1.1 使用 std::istringstream 和 >> 操作符示

C++原地删除有序数组重复项的N种方法

《C++原地删除有序数组重复项的N种方法》给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度,不要使用额外的数组空间,你必须在原地修改输入数组并在使用O(... 目录一、问题二、问题分析三、算法实现四、问题变体:最多保留两次五、分析和代码实现5.1、问题分析5.