未调用派生类的虚拟赋值运算符

derived class's virtual assignment operator not being called

本文关键字:虚拟 赋值运算符 调用 派生      更新时间:2023-10-16

我是c++的新手,正试图掌握虚拟赋值。下面的程序由一个具有两个数据成员的抽象基类和一个具有一个数据成员的派生类组成。当我设置一个指向派生对象的抽象指针时,程序使用operator=的抽象版本而不是派生版本,尽管它们都被声明为"虚"。我哪里做错了?

提前感谢,

周杰伦

#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;
}

c++不允许用协变参数类型覆盖虚函数。您的派生操作符根本不覆盖抽象赋值操作符,它定义了一个完全正交的操作符,仅在操作符名称相同的情况下相关。

创建这样的函数必须小心,因为如果两个实际派生类型不一致,几乎可以肯定赋值将是无意义的。我将重新考虑是否可以通过另一种方法更好地满足您的设计需求。

这句话有点老了,但是如果有人不小心发现了:

要添加到Mark的答案中,您可以通过实现

来实现。
Derived & operator=(const Abstract & rs);

在这种情况下,您可能需要通过强制转换rs: dynamic_cast<const Derived &>(rs)来使用它
当然,这只能小心地做。完整的实现是:

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;
}