首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >c++ 2重载也有类似的转换,具体取决于操作符是成员函数还是全局函数。

c++ 2重载也有类似的转换,具体取决于操作符是成员函数还是全局函数。
EN

Stack Overflow用户
提问于 2021-11-24 23:54:46
回答 1查看 67关注 0票数 1

考虑一个简单的向量类实现:

代码语言:javascript
运行
复制
#include <algorithm>

class Vector {
public:
    Vector(int _elementsCount)
        : elementsCount(_elementsCount)
        , elements(new float[_elementsCount])
    {}
    ~Vector() {
        delete[] elements;
    }
    Vector(const Vector& rhs) {
        elementsCount = rhs.size();
        elements = new float[elementsCount];
        for (int i = 0; i < elementsCount; ++i)
            (*this)[i] = rhs[i];
    }

    float& operator [](int i) {
        return elements[i];
    }
    float operator [](int i) const {
        return const_cast<Vector&>(*this)[i];
    }
    int size() const {
        return elementsCount;
    }
    /*// Dot product
    float operator *(const Vector& v) {
        float res = 0;
        for (int i = 0; i < size(); ++i)
            res += (*this)[i] * v[i];
        return res;
    }*/
private:
    int elementsCount;
    float* elements;
};

// Multiplication by a scalar
Vector operator *(const Vector& v, float k) {
    Vector res(v.size());
    for (int i = 0; i < v.size(); ++i)
        res[i] = v[i] * k;
    return res;
}

// Dot product
float operator *(const Vector& v1, const Vector& v2) {
    float res = 0;
    for (int i = 0; i < std::min(v1.size(), v2.size()); ++i)
        res += v1[i] * v2[i];
    return res;
}

void main()
{
    Vector v(2);
    v * 3; // ambiguous
}

这段代码编译。但是,如果取消类中的*操作符实现,并注释它的全局实现(点积函数),则会出现一个错误“向量::运算符*:2重载有类似的转换”,因为其中有一个歧义:是用标量调用乘法,还是将3解释为参数化构造函数的参数,并调用点积。这说得通。但我不明白将*操作符声明为成员函数或全局函数有什么区别。我认为在上面的例子中它们应该是一样的,但事实并非如此。

补充说,我最感兴趣的不是如何避免歧义,而是为什么在一种情况下(当*被声明为成员时)而在另一种情况下没有歧义(当*被声明为全局函数时)。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-11-25 00:00:17

您需要使构造函数explicit

代码语言:javascript
运行
复制
explicit Vector(int _elementsCount) { ... }

造成这种模糊性的原因是编译器无法决定是隐式地将int值转换为Vector并调用Vector::operator*,还是隐式地将int值转换为float并使用operator*(const Vector&, float)

通过使用explicit,这种转换是被禁止的,如果您希望"3“成为一个Vector,则必须使用Vector(3)

另外,您应该使操作符const,因为它不修改对象。使之成为const还将允许它与const Vector一起使用

代码语言:javascript
运行
复制
float operator *(const Vector& v) const { ... }

请注意,这仍将与您的其他过载冲突:

代码语言:javascript
运行
复制
float operator *(const Vector& v1, const Vector& v2) 

没有理由两者兼得。选择成员函数或全局函数,然后删除另一个函数。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70104318

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档