Virtual assignment operator overloading- how the correct overloaded function is chosen?

送分小仙女□ 提交于 2019-12-22 17:49:05

问题


The following code (from C++ FAQs 24.11) is implementing virtual assignment operator overloading and overriding:

#include <iostream>
using namespace std;

class B{
public:
    virtual ~B() throw();
    virtual B& operator= (const B& b) throw();
};

B::~B() throw(){}

B& B::operator= (const B& b) throw()
{ cout << "B::operator=(const B&)\n"; return *this; }


class D : public B{
public:
    virtual D& operator= (const B& b) throw();
    D& operator= (const D& d) throw();
};

D& D::operator= (const B& b) throw()
{cout << "D::operator= (const B&)\n"; return *this;}

D& D::operator= (const D& d) throw()
{cout << "D::operator= (const D&)\n"; return *this;}


void sample(D& d, B& b, D& d2, B& b2){
    cout << "d = d2:   "; d = d2;
    cout << "d = b2:   "; d = b2;
    cout << "b = b2:   "; b = b2;
    cout << "b = d2:   "; b = d2;
}


int main()
{
    D d, b, d2, b2;
    sample(d,b,d2,b2);
}

and it says the output is:

  • d = d2: D::operator=(const D&)
  • d = b2: D::operator=(const B&)
  • b = b2: D::operator=(const B&)
  • b = d2: D::operator=(const B&)

It says:

"Because the compiler resolves which override to call based on the static type of the parameters, the first assignment is the only one that calls the assignment operator that takes a D; all the others end up calling the assignment operator that takes a B."

and

"The last two calls resolve to the override (D::operator= (const B&)) because the actual class of b in sample() is D. If b had actually been a B, the last two calls would have resolve to (B::operator= (const B&))"

I'm a bit confused, the first paragraph says the compiler looks at the parameter static type to determine which (overloaded?) function call is used, so why does the last case call the operator for the B parameter type, when the argument passed, d2, is declared as type D& d2 in sample()?

EDIT Referring to the answer below, I do not see how the request for B::=(D) can result in D::=(B). What if there was another subclass, E? Why would D::=(B) get called and not E::=(B)? Are we saying if B does not have a function '=' for parameter (D) then the run-time starts looking at whether any derived objects contain such a signature?


回答1:


Overload resolution is done using the static types. Once the overload is picked, the dynamic type is used to determine which overridden version of the function is used. Let me explain each result:

//Every object is a D object, so in
//each case, we expect the virtual calls
//to dispatch to the D version.

//lhs: D, rhs: D, so we expect
//D::operator=(D const&)
cout << "d = d2:   "; d = d2;

//lhs: D, rhs: B, so we expect
//D::operator=(B const&)
cout << "d = b2:   "; d = b2;

//lhs: B, rhs: B, so we expect
//B::operator=(B const&).
//This is virtual, and has been overridden
//in D, so the D version gets called.
cout << "b = b2:   "; b = b2;

//lhs: B, rhs: D, so we expect
//B::operator(D const&).
//This does not exist, so the closest match is used:
//B::operator(B const&). (This is a legal match, 
//because D is a subclass of B).
//This is virtual, and has been overridden
//in D, so the D version gets called.
cout << "b = d2:   "; b = d2;


来源:https://stackoverflow.com/questions/15179854/virtual-assignment-operator-overloading-how-the-correct-overloaded-function-is

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!