问题
I'm pretty new to C++, and am trying to come to grips with virtual assignment. The program below consists of an abstract base class with two data members, and a derived class with one. When I set an abstract pointer to a derived object, the program uses the abstract version of operator= rather than the derived version, even though they're both declared "virtual." What am I doing wrong here?
Thanks in advance,
Jay
#include <iostream>
#include <cstring>
class Abstract
{
protected:
char * label;
int rating;
public:
Abstract(const char * l = "null", int r = 0);
virtual Abstract & operator=(const Abstract & rs);
virtual ~Abstract() { delete [] label; }
virtual void view() const = 0;
};
class Derived : public Abstract
{
private:
char * style;
public:
Derived(const char * s = "none", const char * l = "null",
int r = 0);
~Derived() { delete [] style; }
virtual Derived & operator=(const Derived & rs);
virtual void view() const;
};
Abstract::Abstract(const char * l , int r )
{
label = new char[std::strlen(l) + 1];
std::strcpy(label, l);
rating = r;
}
Abstract & Abstract::operator=(const Abstract & rs)
{
if (this == &rs)
return *this;
delete [] label;
label = new char[std::strlen(rs.label) + 1];
std::strcpy(label, rs.label);
rating = rs.rating;
return *this;
}
Derived::Derived(const char * s, const char * l, int r)
: Abstract(l, r)
{
style = new char[std::strlen(s) + 1];
std::strcpy(style, s);
}
Derived & Derived::operator=(const Derived & hs)
{
if (this == &hs)
return *this;
Abstract::operator=(hs);
style = new char[std::strlen(hs.style) + 1];
std::strcpy(style, hs.style);
return *this;
}
void Derived::view() const
{
std::cout << "label: " << label << "\nrating: "
<< rating << "\nstyle: " << style;
}
int main ()
{
using namespace std;
char label[20], style[20];
int rating;
cout << "label? ";
cin >> label;
cout << "rating? ";
cin >> rating;
cout <<"style? ";
cin >> style;
Derived a;
Abstract * ptr = &a;
Derived b(style, label, rating);
*ptr = b;
ptr->view();
return 0;
}
回答1:
C++ doesn't let you override virtual functions with covariant parameter types. Your derived operator doesn't override the Abstract assignment operator at all, it defines a totally orthogonal operator related only in that it's the same operator name.
You have to be careful creating such functions because if the two actual derived types don't agree, almost certainly the assignment will be nonsensical. I would reconsider whether your design need could be served better by an alternate approach.
回答2:
This is a bit old, but in case anyone else stumbles upon it:
To add to Mark's answer, you can do this by implementing
Derived & operator=(const Abstract & rs);
In this case you may need to use rs
by casting it: dynamic_cast<const Derived &>(rs)
Of course this should only be done carefully.
The full implementation would be:
Derived & Derived::operator=(const Abstract & hs)
{
if (this == &hs)
return *this;
Abstract::operator=(hs);
style = new char[std::strlen(dynamic_cast<const Derived &>(hs).style) + 1];
std::strcpy(style, dynamic_cast<const Derived &>(hs).style);
return *this;
}
来源:https://stackoverflow.com/questions/7946997/derived-classs-virtual-assignment-operator-not-being-called