C++ 类的构造函数和函数调用运算符 () 重载之间的歧义



我能够区分类的构造函数和函数调用运算符()重载。但是,它仍然让用户感到困惑。所以,我只是想得到一些意见,也许从设计的角度来看,编写这些代码的好方法是什么。使用以下简单示例计算看涨期权的收益:

class payoff {
public:
int strike;
payoff (int k): strike(k) {}       // constructor which populates the data member strike. 
int operator()(int s) { return (s > strike) ? s - strike : 0; }     // () overload
};
int main (){
payoff x(5);
cout << x(4) << endl;    // output: 2
return 0;
}

当我做payoff x(5)时,我启动一个类型为 payoff 的变量 x 并将 5 传递给构造函数。但是,当我做x(4)时,我将 4 作为函数参数传递以进行一些计算以获得收益值。看到这里的歧义了吗?()的使用似乎不是很直观。

所以我刚刚开始学习 c++ 中的函数对象/函子,我想知道这是否是设计这种函子的正确方法? 感谢您的回答!

编辑:只需在此函子上添加一些注释,因为看涨期权将具有固定的"罢工",这就是为什么我认为使其成为类的数据成员是合适的。但是,期权的收益可能会有所不同,具体取决于股票价格"s"的价值。因此,在主程序中,我可以计算具有不同股价变动的不同收益水平。

所以我刚刚开始学习 c++ 中的函数对象/函子,我是 想知道这是否是设计这种函子的正确方法?

我不知道这是不是这样,但它是正确的并且常用。

看到这里的歧义了吗?

不!我的意思是,我明白你的意思,但不,我不认为这是一种"歧义"。稍微绕道:小心"歧义"这个词,因为它在C++(和其他语言)中具有非常明确和具体的含义,而不是你的意思。无论如何,将这个词与你的意思一起使用,不,我没有看到"歧义"。任何半体面的C++程序员都可以理解你编写的代码。

更好的方法可能是使用大括号初始化列表(出于其他原因更好):

payoff x{5};
cout << x(4) << endl;

一个更简单的解决方案是使用 lambda:

auto make_payoff_fun(int strike)
{
return [strike](int s) { return  (s > strike) ? s - strike : 0; };
}

int main (){
auto x = make_payoff_func(5);
cout << x(4) << endl;
return 0;
}

无论如何,回到你的模棱两可。你必须看看上下文。是的,两者都x(5),但实际上一个是payoff x(5),鉴于payoff是一种类型,它显然是一个声明。

C++具有上下文敏感的语法,这意味着它具有构造,除非您查看上下文(即构造外部的代码),否则您无法知道它们是什么。语言充满了这些,并且是不可避免的:

int *x = &a;
*x = 24;

我们有两个*x.一个是声明的一部分,*声明指针,另一个是表达式,*是间接寻址运算符。

(foo)(x);

上面的表达是什么?这取决于foox是什么。它可以是:

  • 调用函数foo,对象x作为参数:
  • 强制转换为对象的类型foox
  • 创建使用x初始化的foo类型的临时对象。
  • 对对象operator()的调用foo对象x作为参数。
  • 调用转换运算符(decltype(x))::operator foo()

而且我确信我错过了一些。


你知道还有什么有上下文敏感的语法吗?人类语言。以下是我在互联网上匆忙找到的一些例子:

词汇歧义:

"我去银行了。"(银行可以是一个存钱的地方, 或者它可能是河流的边缘。

"我把账单寄给了约翰。(账单可能是约翰的金额 欠的,或者可能是帽子的账单,所以修理帽子的约翰可以 修理一个。

句法(语法)歧义:

"探亲可能会很累。"(令人筋疲力尽的是:当 亲戚来看你,还是当你探亲时?

"让我们停止控制人。"(这是否意味着"让我们阻止人们 谁控制别人",或者"让我们停止控制别人?

首先,首先将explicit关键字添加到构造函数中。

然后,如果要使构造函数更显式,可以将其设为私有,然后添加一个返回该类实例的公共静态方法create()

最新更新