简体   繁体   中英

Dynamic binding to function depending on arguments in C++

I was expecting the assignment operator to be dynamically bound depending on the argument type:

struct NumberObject;
struct NumberString;

struct DataType
{
    virtual void operator=(DataType& rhs) {};
    virtual void operator=(NumberString& rhs) {};
};
struct NumberObject : DataType
{
    double data = 7;
    void operator=(DataType& rhs)  override
    {
        std::cout << "Copying from DataType\n"; 
// The assignment operator that's called is this one. I was hoping it would be the one below.
    }
    void operator=(NumberString& rhs) override
    {
        std::cout << "Copying from NumberString\n";
    }
};
struct NumberString : DataType
{
    std::string data = "7";
    void operator=(NumberString& rhs) override{};
};


int main()
{
    DataType *pDataType1, *pDataType2;
    pDataType1 = new NumberObject;
    pDataType2 = new NumberString;
    *pDataType1 = *pDataType2;   // Both pointers are to DataType, I was hoping that the assignment operator taking 
                            // NumberString as the right hand side would be called


    return 0;
}

From this I guess that C++ can't dynamically bind functions based on the argument type. The dynamic binding only happens when calling a function directly through an object. So I thought I could do this, but it does seem like a roundabout way:

struct NumberObject : DataType
{
    double data = 7;
    void operator=(DataType& rhs)  override
    {
        std::cout << "Copying from DataType\n";
        rhs.assignTo(*this);
    }
    void operator=(NumberString& rhs) override
    {
        std::cout << "Copying from NumberString\n";
    }
};
struct NumberString : DataType
{
    std::string data = "7";
    void assignTo(NumberObject& lhs) override 
    {// Provided the base class had this
        lhs.data = atof(this->data.c_str());
    }

    void operator=(NumberString& rhs) override{};
};

This seems like a hack, and seeing as though the language is capable of dynamic binding, isn't this something it could do easily? Is it a weakness of the language? Or does nobody care about it?

With double dispatching, it would be:

struct NumberObject;
struct NumberString;

struct DataType
{
    virtual ~DataType() = default;
    virtual void operator=(const DataType&) = 0;
    virtual void assignTo(NumberObject&) const = 0;
    virtual void assignTo(NumberString&) const = 0;
};

struct NumberObject : DataType
{
    double data = 7;
    void operator=(const DataType& rhs) override { rhs.assignTo(*this); }

    void assignTo(NumberObject& rhs) const override
    {
        std::cout << "Copying from NumberObject\n"; 
    }
    void assignTo(NumberString& rhs) const override
    {
        std::cout << "Copying from NumberObject\n";
    }
};

struct NumberString : DataType
{
    std::string data = "7";
    void operator=(const DataType& rhs) override { rhs.assignTo(*this); }

    void assignTo(NumberObject& rhs) const override
    {
        std::cout << "Copying from NumberString\n"; 
    }
    void assignTo(NumberString& rhs) const override
    {
        std::cout << "Copying from NumberString\n";
    }
};

Demo

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM