我可以制作一个对象方法,如果单独调用它会修改自身,但如果在复制初始化期间调用 return 一个新对象吗?

Can I make an object method that will modify itself if called alone but return a new object if called during copy initialization?

我正在编写自定义日期时间 class。是否可以这样做:

datetime mydate;
mydate.to_utc();  // object modifies itself

但是当这样调用时:

datetime mynewdate = mydate.to_utc();

或者像这样:

datetime mynewdate(mydate.to_utc());

我不希望 mydate.to_utc() 修改自身,只希望 initialize/construct mynewdate 的值为 mydate.to_utc();

谢谢,

虽然我同意其他人的观点,将 API 这样混合通常是个坏主意,但无论如何有一个简单的方法可以解决它:使非 returning 函数不 return 任何东西(当然)并使 returning 函数 const 合格。成员函数const限定是函数签名的一部分,可以用来区分重载。

像这样:

class datetime
{
public:
    // ...

    // This function modifies the current object in place
    void to_utc();

    // This function returns a new datetime object
    datetime to_utc() const;
};

类似于上面的代码在 "setters" 和 "getters" 中并不少见,但是编译器能够区分 "setter" 和 "getter" 也有参数("setter" 有参数,"getter" 没有)。

"setters" 和 "getters" 与上述代码之间的区别是(如前所述)编译器可以通过以下方式区分 "setter" 和 "getter"争论。这不可能与我对所问问题的上述解决方案有关。并且可能导致构建错误,如评论中所述。提供的解决方案在某些情况下可能有效,但在其他情况下无效,因此使用时应谨慎。

使用 C++ 无法实现您想要实现的目标:重载解析完全独立于 return 类型 – 以及是否评估此类型。

所以这两个不同的重载

void to_utc();     // self-modifying
datetime to_utc(); // returning new object

永远都是模棱两可的。

现在您可以尝试通过将其中之一设为常量(如Some programmer dude )来区分它们,但这不会产生您想要的效果:

datetime dt0;
datetime dt1 = dt0.to_utc();

dt0 不是 const,因此重载决策也会 select 非常量重载,并且您最终会 dt0 再次修改自身。更糟糕的是:由于 selected 重载 returns void,代码甚至无法编译。您现在可以通过适当地转换来解决这个问题:

datetime dt1 = const_cast<datetime const>(dt0).to_utc();

不过,如果这在问题的意义上,我有很多疑问......

实际上剩下的是重命名两个重载之一:

void to_utc();           // self-modifying
datetime as_utc() const; // creating a copy
//                ^^^^^
// independent from given problem: the function won't modify 'this' object
// so having it const still is a good idea...

或者你有一个重载作为独立的(或静态的;不过我更喜欢前者)函数,e。 g.:

datetime to_utc();

void to_utc(datetime&);

我个人会保留两个不同名称的成员函数,但是...

我通常最终做的是提供两个功能:

struct datetime
{
    // mutate the object itself
    void apply_to_utc();

    // return the new object
    auto to_utc() const -> datetime;

};

这使得调用哪个函数以及调用者的意图变得更加清晰。