C++虚赋值运算符

C++ virtual assignment operator

我正在尝试从派生的 class(点)中的基数 class(形状)调用赋值运算符。我收到未解决的外部链接器错误,我不明白为什么。我将 "virtual" 放在基本赋值运算符的前面,并将基本赋值运算符放在派生的 class 的最后。我哪里做错了?

#ifndef SHAPE_H
#define SHAPE_H
#include <iostream>

using namespace std;

namespace Joe
{
    namespace CAD
    {
        class Shape
        {
        private:
            int m_id;
        public:
            Shape();    //default constructor
            ~Shape();    //destructor
            Shape(const Shape& s);    //copy constructor
            virtual Shape& operator = (const Shape& source);    //assignment operator
            string ToString() const;    //returns id as a string
            friend ostream& operator << (ostream& os, const Shape& sh);    //global function that can access private members
            int ID() const;
        };

        inline int Shape::ID() const    //retrieve ID of shape
            {
                return m_id;
            }
    }
}
#endif

#ifndef POINT_H
#define POINT_H
#include <iostream>
#include "shape.h"

namespace Joe
{
    namespace CAD
    {
        class Point: public Shape
        {
        private:
            double m_x;
            double m_y;
        public:
            Point();    //default constructor
            ~Point();    //destructor
            Point(const Point& pt);    //copy constructor
            Point(double newX, double newY)    //constructor accepting x and y coordinates
            {
                m_x = newX;
                m_y = newY;
                std::cout << "Point(" << m_x <<","<< m_y <<")" << std::endl;
            }

            Point(double val);    //constructor accepting one double

            void X(double newXval) {m_x = newXval;}    //default inline setter
            void Y(double newYval) {m_y = newYval;}    //default inline setter

            double X() const;    //getter pre-inline
            double Y() const;    //getter pre-inline


            std::string ToString() const;    //returns a string description

            //distance functions
            double Distance() const;    //calculate the distance to the origin (0,0)
            double Distance(const Point& p) const;    //calculate the distance between two points

            //operator overloading
            Point operator - () const;    //negate the coordinates
            Point operator * (double factor) const;    //scale the coordinates
            Point operator + (const Point& p) const;    //add coordinates
            bool operator == (const Point& p) const;    //equally compare operator
            Point& operator = (const Point& source);    //assignment operator
            Point& operator *= (double factor);    //scale the coordinates and assign

            friend std::ostream& operator << (std::ostream& os, const Point& p);    //send to ostream (friend)
            Shape& operator = (const Shape& source);    // call assignment operator of base class
        };

        inline double Point::X() const    //normal inline getter
        {
            return m_x;
        }

        inline double Point::Y() const    //normal inline getter
        {
            return m_y;
        }
    }
}
#endif

Shape& Shape::operator = (const Shape& source)    //assignment operator
        {
            if (this == &source)    //avoid self-assignment
                return *this;
            cout << "shape assignment" << endl;
            m_id = source.m_id;
            return *this;
        }

Point& Point::operator = (const Point& source)    //assign
        {
            if (this == &source)    //avoid self-assignment
                return *this;
            m_x = source.m_x;
            m_y = source.m_y;
            return *this;
        }

您的问题可能是您在命名空间中定义了 class,但是您在该命名空间之外定义了运算符而没有指定它。因此,编译器无法将定义连接到声明。

Ishamael 指出您没有指定将非点形状分配给点时会发生什么。这对于虚拟赋值运算符是必需的;看到他的回答。但是这个虚拟赋值运算符最终可能会做很多意想不到的事情,比如如果错误的类型被分配给彼此,就会切断部分对象。

您不需要虚拟性来确保在分配 Point 时也调用 Shape 运算符。只需在 Point 运算符中调用 Shape 运算符。使运算符虚拟化实际上会产生相反的效果; Point 运算符将覆盖 Shape 运算符,即使您调用它的实例被称为 Shape。

Point& Point::operator = (const Point& source)    //assign
    {
        if (this == &source)    //avoid self-assignment
            return *this;
        Shape::operator=(source);  // also call the base class operator
        m_x = source.m_x;
        m_y = source.m_y;
        return *this;
    }

你的问题是,当你调用 operator = 并传递给它一个 Shape 时,你正在调用 Point::operator=(const Shape&),你没有定义它,你只定义了 Shape::operator=(const Shape&)Point::operator=(const Point&)。您需要添加 Point::operator=(const Shape&),例如:

    Shape& Point::operator = (const Shape& shape)    //assign
    {
        const Point& source = static_cast<Point&>(shape); // or use dynamic_cast here, if you want to be safe
        if (this == &source)    //avoid self-assignment
            return *this;
        m_x = source.m_x;
        m_y = source.m_y;
        return *this;
    }