【问题标题】:derived class's virtual assignment operator not being called未调用派生类的虚拟赋值运算符
【发布时间】:2011-10-30 18:50:29
【问题描述】:

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

【问题讨论】:

  • 不相关,但你为什么使用char*s?
  • 不深入细节,你做错了。阅读learncpp.com/cpp-tutorial/…,并在谷歌搜索“虚拟赋值运算符”。这已经讨论了很多了。
  • 为了缩短代码,我尝试删除与我的问题无关的内容,包括动态内存(因此是 char *s)
  • 嗨,Seth,我已经花了很多时间搜索谷歌(和这个网站)。我已经看过你链接到的页面了。
  • *ptr 部分取消引用指针以获取实际对象,然后在该对象上调用operator=。不发生虚方法查找。

标签: c++ assignment-operator


【解决方案1】:

C++ 不允许您使用协变参数类型覆盖虚函数。您的派生运算符根本不会覆盖抽象赋值运算符,它定义了一个完全正交的运算符,仅因为它是相同的运算符名称而相关。

您必须小心创建此类函数,因为如果两个实际派生类型不一致,几乎可以肯定该分配将是荒谬的。我会重新考虑是否可以通过其他方法更好地满足您的设计需求。

【讨论】:

  • 也很有帮助。谢谢。
【解决方案2】:

这有点旧,但以防其他人偶然发现它:

要添加到马克的答案,您可以通过实施来做到这一点

Derived & operator=(const Abstract & rs);

在这种情况下,您可能需要使用 rs 通过强制转换:dynamic_cast&lt;const Derived &amp;&gt;(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;
}

【讨论】:

    猜你喜欢
    • 2016-07-10
    • 1970-01-01
    • 2013-03-03
    • 2010-10-14
    • 2012-02-12
    • 2021-07-31
    • 2020-02-16
    相关资源
    最近更新 更多