覆盖派生类中的二进制运算符

问题描述 投票:0回答:1

目前我正在研究一些代数问题。我有一个(几乎是抽象的)基类,从这个基类中可以派生出若干类。所有这些类都将包含以许多不同方式排序的数字列表.在基类上,我想定义一些运算符,这些运算符将为每个派生类实现。我们的想法是,一旦这个库完成,我就不必再关心派生类的本质。一旦我初始化了某个派生类,我就可以通过基类型的引用(或指针)来引用它,并通过它来访问所有的派生操作。

我想在基类上定义的操作的基础上,设置相当复杂的算法。因此,我希望能够只通过基类来访问这些算法。这样一来,它应该很容易地泛化到许多类型的派生类中去。我已经明白,这正是面向对象的编程,所以这就是为什么我最终使用了C++。

我已经用类似于这个例子的方式设置了大部分我想要的东西(与g++一起工作)。

#include <iostream>
class base;
base & gettype(const base&);
class base{
    public:
    int x;
    int type;
    base() = default;
    base(int in){
        this->type=0;
        this->x = in;
    }
    virtual base & operator+= ( const base & other){
        this->x += other.x;
        return *this;
    }
    virtual base & operator+ ( const base & other){
        base & ret = gettype(*this);
        ret += other.x;
        return ret;
    }
    virtual void print(){
        std::cout << "base is: " << x << "\n";
    }
};
class der1:public base{
    public:
    int a;
    der1(){}
    der1(int in){
        this->x = in;
        this->a = 2*in;
        this->type=1;

    }
    base & operator+= ( const base & other){
        std::cout <<"used der add\n";
        const der1 & otherder = static_cast<const der1 &>(other);
        this->x += otherder.x;
        this->a += otherder.a;
        return *this;
    }
    void print(){
        std::cout << "der1 is: " << x << " " << a << "\n";
    }
};
base & gettype(const base & in){
    if(in.type==0){
        return * new base();
    }
    if(in.type==1){
        return * new der1();
    }
}

main(){
    base baseobj(2);
    baseobj.print();
    baseobj += baseobj;
    baseobj.print();
    (baseobj+baseobj).print(); //Answer is right, but there is a memory leak

    der1 derobj(3);
    derobj.print();
    derobj += derobj;
    base * test = new der1(4);
    test->print();
    (*test) += (*test);
    test->print();
    base & test2 = *test;
    test2 += test2;
    test2.print(); //All these print the right answers as well
    delete test; 
}

但这里面有一个内存泄漏的问题。每当我做这样的事情时 x=x+y,那么在gettype函数中分配的内存就不会再被释放了。

我读到过,有一个很不常见的 operator+ 函数返回一个引用。然而,我无法以令人满意的方式使之工作,当 operator+ 按值返回。原因是,当它按值返回时,它将返回一个以 base 对象。当我定义派生 operator+ 函数(如下面的例子),它们没有被使用,因为我只使用了 base 类型引用,而不是 der1.

#include <iostream>
class base{
    public:
    int x;
    base() = default;
    base(int in){
        this->x = in;
    }
    virtual base & operator+= ( const base & other){
        this->x += other.x;
        return *this;
    }
    virtual base operator+ ( const base & other){
        base ret(*this);
        ret += other.x;
        return ret;
    }
    virtual void print(){
        std::cout << "base is: " << x << "\n";
    }
};
class der1:public base{
    public:
    int a;
    der1(int in){
        this->x = in;
        this->a = 2*in;
    }
    der1 & operator+= ( const der1 & other){
        this->x += other.x;
        this->a += other.a;
        return *this;
    }
    der1 operator+ ( const der1 & other){
        der1 ret(*this);
        ret += other.x;
        return ret;
    }
    void print(){
        std::cout << "der1 is: " << x << " " << a << "\n";
    }
};

main(){
    base baseobj(2);
    baseobj.print();
    baseobj += baseobj;
    baseobj.print();
    (baseobj+baseobj).print();  //This all works nicely for the base class

    der1 derobj(3);
    derobj.print();
    base * test = new der1(4);
    test->print(); //derived print function
    base & test2 = *test;
    test2 += test2; //base add function, because argument base&
    test2.print(); //Indeed, wrong answer.

}

那么,是否可以创建一个库,让我以类似的方式使用。

base & x = getderived(3) // This will return a (reference/pointer to) derived type
base & y = getderived(3)
x +=y;
x = x+3*y;
//And a whole lot of other operations

delete x
delete y // I don't mine some manual memory management

我希望你能明白我想达到什么目的。如果你认为这是不可能的,我也很乐意与这个答案,那么我知道我必须停止进一步寻找。(如果没有解决办法,我就保持现在的方法,只能用 += 样的运算符,而跳过二进制的。这也不完全是坏事)

c++ inheritance overloading operator-keyword
1个回答
1
投票

在C++中,你不应该使用显式 newdelete 而你应该遵循 RAII.

如果我明白你的问题,我会摆脱的。typegettype 而改用虚拟的 clone:

class base
{
public:
    virtual std::unique_ptr<base> clone() const
    {
        return std::make_unique<base>(*this);
    }
};

class derived : public base
{
public:
    std::unique_ptr<base> clone() const override
    {
        return std::make_unique<derived>(*this);
    }
};
© www.soinside.com 2019 - 2024. All rights reserved.