RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 620761
Accepted
Maxmaxmaximus
Maxmaxmaximus
Asked:2020-01-29 14:02:58 +0000 UTC2020-01-29 14:02:58 +0000 UTC 2020-01-29 14:02:58 +0000 UTC

重载加法运算符

  • 772
class Cat {
private:
    int value = 1;

public:
    Cat(int _value) {
        value = _value;
    }

    operator+(Cat a, Cat b) {
        return new Cat(a.value + b.value);
    }
};

似乎我写的一切都是正确的,两只猫的加法会产生一只新猫,其价值将是它们价值的总和。但是我得到两个错误。

main.cpp:17:5: error: C++ requires a type specifier for all declarations
    operator+(Cat a, Cat b) {
    ^
main.cpp:18:16: error: cannot initialize return object of type 'int' with an rvalue of type 'Cat *'
        return new Cat(a.value + b.value);
               ^~~~~~~~~~~~~~~~~~~~~~~~~~
2 errors generated.
c++
  • 3 3 个回答
  • 10 Views

3 个回答

  • Voted
  1. Best Answer
    Harry
    2020-01-29T14:31:44Z2020-01-29T14:31:44Z

    谁来声明返回类型?

    Cat* operator+(Cat a, Cat b) {
        return new Cat(a.value + b.value);
    }
    

    只有这样,首先不是解决方案,其次是不好的解决方案。

    不是解决方案 - 因为通常运算符是+二进制的。它添加了两个值,并且您有三个值参与添加- 也是您的对象 ( this)。

    Cat* operator+(Cat b) {
        return new Cat(this->value + b.value);
    }
    

    现在这是解决方案。但是不好。因为它返回的不是猫,而是指向它的指针。结果,调用函数负责强制保存该值并在将来释放内存。

    这可以通过返回完成的猫来避免:

    Cat operator+(Cat b) {
        return Cat(this->value + b.value);
    }
    

    最后一个。如果猫很大(不是按值计算value,而是占用大量内存),那么不按值而是按引用将它传递给运算符是有意义的:

    Cat operator+(const Cat& b) {
        return Cat(this->value + b.value);
    }
    
    • 16
  2. Vlad from Moscow
    2020-01-29T19:53:23Z2020-01-29T19:53:23Z

    二元运算符(例如加法运算符)operator +必须定义为具有一个参数的非静态类成员函数,或者定义为具有两个参数的非类成员函数。

    给你的编译器信息

    main.cpp:17:5: error: C++ requires a type specifier for all declarations
        operator+(Cat a, Cat b) {
        ^
    main.cpp:18:16: error: cannot initialize return object of type 'int' with an rvalue of type 'Cat *'
            return new Cat(a.value + b.value);
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~
    

    假设您定义的运算符没有返回类型。

    只有转换函数可能没有返回类型。对于加法运算符,您必须指定返回值的类型。

    添加两个类对象时,返回指向该对象的指针没有任何意义。在这种情况下,您将无法在没有附加运算符的情况下链接加法运算符,而且可能会泄漏内存。

    运算符必须返回对象本身,带const或不带限定符。

    如上所述,可以将运算符声明为具有一个参数的非静态类成员函数。

    在这种情况下,运算符operator +可能看起来像这样

    class Cat 
    {
    private:
        int value = 1;
    
    public:
        Cat(int _value) 
        {
            value = _value;
        }
    
        Cat operator +( const Cat &a ) const 
        {
            return Cat( this->value + a.value );
        }
    };
    

    或者如何

    class Cat 
    {
    private:
        int value = 1;
    
    public:
        Cat(int _value) 
        {
            value = _value;
        }
    
        const Cat operator +( const Cat &a ) const 
        {
            return Cat( this->value + a.value );
        }
    };
    

    您也可以为rvalue-references 重载运算符,例如

    Cat operator +( const Cat &&a ) const 
    {
        return Cat( this->value + a.value );
    }
    

    或者

    Cat operator +( Cat &&a ) const 
    {
        return Cat( this->value + a.value );
    }
    

    但是对于这么一个简单的不抓取大资源的类来说,这无所谓。

    condt请注意参数列表后的限定词。这意味着将出现在运算符左侧的对象本身不会改变,就像右侧对象一样,因为与其对应的运算符参数也是用限定符定义的const。

    请记住,由于类构造函数被声明为转换构造函数,因此Cat在这种情况下您可以添加带有数字的类对象。例如,

    #include <iostream>
    
    class Cat 
    {
    private:
        int value = 1;
    
    public:
        Cat(int _value) 
        {
            value = _value;
        }
    
        const Cat operator +( const Cat &a ) const 
        {
            return Cat( this->value + a.value );
        }
    };
    
    int main() 
    {
        Cat c1( 10 );
    
        c1 + 5.5;
    
        return 0;
    }
    

    这是否合理由您决定,具体取决于此加法运算符的含义。如果您不想允许这种从数字到类对象的隐式转换Cat,那么您可以将构造函数声明为显式。在这种情况下,如果程序试图将类对象添加Cat到数字,则程序将不会编译。

    #include <iostream>
    
    class Cat 
    {
    private:
        int value = 1;
    
    public:
        explicit Cat(int _value) 
        {
            value = _value;
        }
    
        const Cat operator +( const Cat &a ) const 
        {
            return Cat( this->value + a.value );
        }
    };
    
    int main() 
    {
        Cat c1( 10 );
    
        c1 + 5.5;
    
        return 0;
    }
    

    对于这个程序,编译器会产生类似下面的错误信息

    prog.cpp:24:5: error: no match for 'operator+' (operand types are 'Cat' and 'double')
      c1 + 5.5;
         ^
    

    声明此运算符的第二种方法是将其声明为函数,该函数不是类的成员。由于此函数必须有权访问私有类成员value,因此需要将其声明为该类的友元函数。

    您可以在类定义内部和外部定义函数本身。

    例如,

    #include <iostream>
    
    class Cat 
    {
    private:
        int value = 1;
    
    public:
        Cat(int _value) 
        {
            value = _value;
        }
    
        friend const Cat operator +( const Cat &a, const Cat &b )  
        {
            return Cat( a.value + b.value );
        }
    };
    
    int main() 
    {
        Cat c1( 10 );
        Cat c2( 5 );
    
        Cat c3 = c1 + c2;
    
        return 0;
    }
    

    请记住,声明以下划线开头的变量是个坏主意。通常,此类以下划线开头的名称是编译器保留的。

    构造函数参数的名称通常与类成员的名称相对应。在这种情况下,您可以立即看到哪个参数初始化了类的哪个成员。所以你可以像这样定义一个构造函数

    Cat( int value ) : value( value )
    {
    }
    

    如果一个类成员value不能取负值,那么最好将它和相应的构造函数参数声明为具有类型unsigned int。

    • 4
  3. isnullxbh
    2020-01-29T18:56:02Z2020-01-29T18:56:02Z

    使用friend:

    #include <iostream>
    
    class Foo
    {
    public:
        Foo( int p_a )
            : m_a( p_a )
        {}
    
        int getA() const { return m_a; }
    
    protected:
        int m_a;
    
    friend Foo operator+( Foo const& lF, Foo const& rF )
    {
        return Foo( lF.m_a + rF.m_a );  
    }
    
    };
    
    
    int main() {
    
        Foo f1( 12 ), f2( 13 ), f4( 14 );
    
        Foo f3 = f1 + f2 + f4;
    
        std::cout << f3.getA() << std::endl;
    
        return 0;
    }
    
    • 0

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    Python 3.6 - 安装 MySQL (Windows)

    • 1 个回答
  • Marko Smith

    C++ 编写程序“计算单个岛屿”。填充一个二维数组 12x12 0 和 1

    • 2 个回答
  • Marko Smith

    返回指针的函数

    • 1 个回答
  • Marko Smith

    我使用 django 管理面板添加图像,但它没有显示

    • 1 个回答
  • Marko Smith

    这些条目是什么意思,它们的完整等效项是什么样的

    • 2 个回答
  • Marko Smith

    浏览器仍然缓存文件数据

    • 1 个回答
  • Marko Smith

    在 Excel VBA 中激活工作表的问题

    • 3 个回答
  • Marko Smith

    为什么内置类型中包含复数而小数不包含?

    • 2 个回答
  • Marko Smith

    获得唯一途径

    • 3 个回答
  • Marko Smith

    告诉我一个像幻灯片一样创建滚动的库

    • 1 个回答
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Алексей Шиманский 如何以及通过什么方式来查找 Javascript 代码中的错误? 2020-08-03 00:21:37 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    user207618 Codegolf——组合选择算法的实现 2020-10-23 18:46:29 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5