本文主要是介绍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++逻辑设计——函数设计之函数接口说明的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!