C++运算符重载:不同重载方式的问题

原题:

狐狸精

描述

反派是三只成精的狐狸:狐母,狐女和狐子阿拐。
狐狸成精后,开始作恶多端。假设有Fox类,有自己的大小int size和法力int power
狐狸精甲如果和狐狸精乙合体(&&),会变成一只更大的狐狸丙,size变成原来甲和乙的size之和,power会变成原来甲和乙的power平均值。
狐狸还会飘(~),飘的时候,size会自动变成原来的三分之一。

请参考下面的main用一个Fox类来实现这些法力。

int main()
{
    int s1, p1, s2, p2;
    cin >> s1 >> p1 >> s2 >> p2;

    Fox C1(s1, p1);
    Fox C2(s2, p2);

    C1.show();    // 现身

    ~(~C1);        // 飘2次
    C1.show();    // 再现身

    Fox C3 = C1 && C2;    // 合体
    C3.show();    // 现身

    return 0;
}

输入

两只狐狸的信息size power

输出

main函数输出及输出样例。其中,show函数依次输出size power,中间以空格分隔,最后换行。

输入样例 1 

100 50 120 80

输出样例 1

100 50
11 50
131 65

提示

  1. 仅需提交Fox类代码和相关函数代码。
  2. 实现相关运算符重载。飘2次的地方注意函数返回值写法。
  3. 整数计算过程不考虑小数部分。

来源 hlu

问题:

Fox& operator~()
	{
		size/=3;
		return *this;
	}
Fox operator~()
	{
		return Fox(size/3, power);
	}
Fox& operator~()
	{
		return Fox(size / 3, power);
	}

为什么这三种写法看起来一样却又不同结果?在这道题中,只有第一种正确,第三中甚至不能正确编译

解决:

在这个问题中,我们需要考虑C++运算符重载的语义和返回类型。对于单目运算符~,如果我们要实现一个“飘”的功能,通常我们会希望这个操作能够改变当前对象的状态,并且能够链式调用(即连续飘多次)。这就要求我们的重载运算符能够返回一个引用,以便可以连续调用。

  1. 第一种写法Fox& operator~() { size /= 3; return *this; }这种写法是正确的,因为它返回了当前对象的引用,允许链式调用。例如,~(~C1)首先对C1调用一次~,然后使用结果再次调用~,因为每次调用都返回了对象的引用。
  2. 第二种写法Fox operator~() { return Fox(size / 3, power); }这种写法返回了一个新的Fox对象,而不是引用。这在逻辑上是有问题的,因为如果按照这种写法,~(~C1)将不会工作,因为第一个~会返回一个新的Fox对象,而第二个~无法在这个新对象上调用来实现链式飘的效果。
  3. 第三种写法Fox& operator~() { return Fox(size / 3, power); }这种写法试图返回当前对象的引用,但实际上返回的是新创建对象的引用。这是有问题的,因为返回的引用指向的是一个局部的临时对象,一旦函数返回,这个局部对象的生命周期就结束了,导致返回的引用悬空(dangling reference)。这将导致未定义行为,编译器通常也会报错,因为它违反了C++的规则。

总结一下:

为什么这些写法不同?

1. 语义差异

  • 第一种写法修改当前对象,适用于需要改变对象状态的场景。
  • 第二种写法创建新对象,适用于需要保留原始对象的场景。
  • 第三种写法在语义上是混乱的,因为它试图返回一个引用,但实际上返回的是局部对象的引用。

2. 编译问题

  • 第一种写法是正确的,因为它遵循了C++的规则。
  • 第二种写法虽然逻辑上有问题,但至少可以编译通过。
  • 第三种写法违反了C++的规则,因为它试图返回局部对象的引用,这会导致编译错误。

AC源码:

#include<iostream>

using namespace std;

class Fox
{
private:
	int size;
	int power;
public:
	Fox(int s,int p):size(s),power(p)
	{
	}
	void show()
	{
		cout<<size<<" "<<power<<endl;
	}
	
	Fox& operator~()
	{
		size/=3;
		return *this;
	}
	
	
	friend Fox operator&&(Fox & c1,Fox & c2);
};

Fox operator&&(Fox & c1,Fox & c2)
	{
		return Fox(c1.size+c2.size,(c1.power+c2.power)/2);
	}

int main()
{
    int s1, p1, s2, p2;
    cin >> s1 >> p1 >> s2 >> p2;

    Fox C1(s1, p1);
    Fox C2(s2, p2);

    C1.show();    // 现身

    ~(~C1);        // 飘2次
    C1.show();    // 再现身

    Fox C3 = C1 && C2;    // 合体
    C3.show();    // 现身

    return 0;
}
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇