C ++重载虚拟+运算符 [英] c++ overloading virtual + operator

查看:111
本文介绍了C ++重载虚拟+运算符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

#include <iostream>

class aa
{
public:
    aa(){}

    aa(aa& obj)
    {
        aa1 = obj.aa1;
    }

    virtual aa operator =(aa& obj)
    {
        aa1 = obj.aa1;
        return (*this);
    }

    virtual aa operator +(aa& obj)
    {
        aa1 += obj.aa1;
        return (*this);
    }

    int aa1;
};

class bb: public aa
{
public:
    bb():aa(){}

    bb(bb& obj)
    {
        bb1 = obj.bb1;
    }

    aa operator =(aa& obj)
    {
        aa::operator =(obj);
        bb b1 = dynamic_cast<bb&>(obj);
        bb1 = b1.bb1;       
        return (*this);
    }

    aa operator +(aa& obj)
    {
        aa::operator +(obj);
        bb b1 = dynamic_cast<bb&>(obj);
        bb1 += b1.bb1;
        return (*this);
    }

    int bb1;
};


int main()
{
    bb b1;
    bb b2;

    b1.bb1 = 1;
    b1.aa1 = 1;

    b2.bb1 = 2;
    b2.aa1 = 2;

    aa &a1 = b1;
    aa &a2 = b2;

    a1 = a2;
    b1 = dynamic_cast<bb&>(a1);
    b2 = dynamic_cast<bb&>(a2);

    std::cout<<b1.aa1<<";"<<b1.bb1;

    bb b3;
    b3.bb1 = 3;
    b3.aa1 = 3;

    aa &a3 = b3;

    aa &a4 = a2 + a3;
    b3 = dynamic_cast<bb&>(a4);

    return 0;
}

输出: 2;2,然后在b3 = dynamic_cast<bb&>(a4);行崩溃,给出错误std::bad_cast at memory location 0x0012fdbc..

Output: 2;2 and then it crashes at line b3 = dynamic_cast<bb&>(a4); giving the error std::bad_cast at memory location 0x0012fdbc..

我发现的原因是a2 + a3的表达式的结果作为aa类型的对象来了,在下一条语句中,我们试图将其强制转换为无效的派生类型对象,从而导致异常.所以我的疑问是我们能否实现上述目的,即aa &a4 = a2 + a3;在上述功能上进行一些更改?

The reason I have found is the result of expression of a2+a3 is coming as object of type aa, and in the next statement we are trying to cast it to derived type object which is not valid, hence leading to exception. So my query is can we achieve the above intention i.e. aa &a4 = a2 + a3; with some changes in the above functions?

推荐答案

C ++具有一个调度程序(基于虚函数). 多态二进制运算符不可避免地属于双重调度"情况,因此不能仅通过简单的虚函数实现多态.

C++ has a single dispatch (based on virtual function). Polymorphic binary operators fall inevitably into the "dual dispatch" case, and hence cannot be implemented polymorphicaly by means of just simple virtual function.

此外,由于您要返回一个值,因此所有子类信息都将丢失.

Also, since you are returning a value, every sub-classes information is lost.

处理这种情况的更合适的方法是定义一个非多态句柄,该句柄实现操作并保存多态类型,并委托它们执行操作.

A more proper way to handle this kind of situation is to define a non-polymorphic handle that implements the operations and holds polymorphic types, delegating to them the operation execution.

喜欢

class handle
{
public:
    class aa;
    class bb;

    class root
    {
    public:
        virtual ~root() {}         //< required being this polymorphic
        virtual root* clone()=0;

        virtual handle add_invoke(const root& r) const=0; //resolve the 2nd argument
        virtual handle add(const aa& a) const=0;    //resolve the 1st argument
        virtual handle add(const bb& a) const=0;    //resolve the 1st argument
    };

    class aa: public root
    {
    public:
        aa(...) { /*set vith a value */ }
        aa(const aa& a) { /* copy */ }
        virtual root* clone() { return new aa(*this); }

        virtual handle add_invoke(const root& r) const 
        { return r.add(*this); }  //will call add(const aa&);

        virtual handle add(const aa& a) const
        { return handle(new aa(.../*new value for aa with (aa,aa)*/)); }
        virtual handle add(const bb& a) const
        { return handle(new bb(.../*new value for bb with(aa,bb)*/)); }
    };

    class bb: public root
    {
    public:
        bb(...) { /*set vith a value */ }
        bb(const bb& b) { /* copy */ }
        virtual root* clone() { return new bb(*this); }

        virtual handle add_invoke(const root& r) const
        { return r.add(*this); }  //will call add(const bb&);

        virtual handle add(const aa& a) const
        { return handle(new bb(.../*new value for aa with (bb,aa)*/)); }
        virtual handle add(const bb& a) const
        { return handle(new bb(.../*new value for bb with (bb,bb)*/)); }
    };

    handle() :ps() {}
    //support both copy (by clone) and move (by stole)
    handle(const handle& s) :ps(s.ps? s.ps->clone(): nullptr) {}
    handle(handle&& s) :ps(s.ps) { s.ps=nullptr; };
    //assign by value, to force temporary assign
    handle& operator=(handle h) { delete ps; ps=h.ps; h.ps=0; return *this; }
    //cleanup
    ~handle() { delete ps; }

    //the operator+
    friend handle operator+(const handle& a, const handle& b)
    { 
        return (b.ps && a.ps)? b.ps->add_invoke(*a.ps): handle(); 
        //Note: manage also the a+b with one of `a` or `b` as null, if it make sense
    }

private:
    handle(root* p) :ps(p) {}

    root* ps;
};

这篇关于C ++重载虚拟+运算符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆