关于 C++ 上虚拟运算符*的问题

发布于 2024-12-05 10:33:56 字数 729 浏览 1 评论 0原文

我试图在 C++ 上创建虚拟运算符

class Data
{
    virtual Matrix operator* (Matrix &_matrix);
    virtual Scalar operator* (Scalar &_scalar);
};

class Matrix : public Data
{
private:
    vector<vector<double>> data;
public:
    // ...
    Matrix operator* (Matrix &_matrix);
};

class Scalar : public Data
{
private:
    double data;
public:
    // ...
    Scalar operator* (Scalar &_scalar);
};

,问题是,当我创建如下所示的 Data* 数组时

Data* arr[10];
arr[0] = new Matrix(3,3);
arr[1] = new Matrix(3,3);

arr[0]->operator*(arr[1]);

,我无法在这两个矩阵之间进行乘法,因为我无法将 Data 作为参数传递。 但问题是,我无法使函数的参数采用 Data* 类型,因为它将无法访问 Matrix 或 Scalar 对象的私有成员。

遇到这种奇怪的情况该如何处理呢?

I was trying to make virtual operator on C++

class Data
{
    virtual Matrix operator* (Matrix &_matrix);
    virtual Scalar operator* (Scalar &_scalar);
};

class Matrix : public Data
{
private:
    vector<vector<double>> data;
public:
    // ...
    Matrix operator* (Matrix &_matrix);
};

class Scalar : public Data
{
private:
    double data;
public:
    // ...
    Scalar operator* (Scalar &_scalar);
};

And the problem was, when I created Data* Array like below

Data* arr[10];
arr[0] = new Matrix(3,3);
arr[1] = new Matrix(3,3);

arr[0]->operator*(arr[1]);

I could not do multiplication between these two matrices, since I cannot pass Data as an argument.
But the problem is, I cannot make the function's argument to take Data* type because, it will not be able to access private members of Matrix or Scalar objects.

How to deal with this kind of weird situation?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

内心旳酸楚 2024-12-12 10:33:56

类双重调度问题 - 参见 Meyer 的(忘了是哪一个)。
您需要运算符在左侧和右侧都是虚拟的,因此您需要两个虚拟调用:

class Matrix;
class Scalar;

class Data
{
public:
    virtual Data* operator* (Data& data) = 0;
    virtual Data* operator* (Matrix &matrix) = 0;
    virtual Data* operator* (Scalar &scalar) = 0;
};

class Matrix : public Data
{
private:
    std::vector<std::vector<double>> data;

    // ...
public:
    Matrix* operator* (Matrix &_matrix)
    {
        // implement
    }
    Matrix* operator* (Scalar& scalar)
    {
        // implement
    }
    Data* operator* (Data &data)
    {
        // Magic here - *this is now Matrix, not Data
        return data * (*this);
    }
};

class Scalar : public Data
{
private:
    double data;
public:
    // ...
    Data* operator* (Data& data)
    {
        // Magic here - *this is now Scalar, not Data
        return data * (*this);
    }
    Scalar* operator* (Scalar &scalar)
    {
        // implement
    }

    Matrix* operator* (Matrix &matrix)
    {
        // Note how we need to allow for parameter reveral during the double dispatch
        Matrix& lhs = matrix;
        Matrix& rhs = *this;
        // Compute matrix product lhs * rhs
    }

};

我已经掩盖了返回类型和内存管理的问题。与通常的运算符一样,您最好将 *= 定义为原语。然后,这可以返回对*this的引用。然后可以根据*= 定义* 运算符。再说一次,这是在“Effective C++”中。

Class double dispatch problem - See Meyer's (forget which one).
You need the operator to be virtual on both the lhs and rhs, so you need two virtual calls:

class Matrix;
class Scalar;

class Data
{
public:
    virtual Data* operator* (Data& data) = 0;
    virtual Data* operator* (Matrix &matrix) = 0;
    virtual Data* operator* (Scalar &scalar) = 0;
};

class Matrix : public Data
{
private:
    std::vector<std::vector<double>> data;

    // ...
public:
    Matrix* operator* (Matrix &_matrix)
    {
        // implement
    }
    Matrix* operator* (Scalar& scalar)
    {
        // implement
    }
    Data* operator* (Data &data)
    {
        // Magic here - *this is now Matrix, not Data
        return data * (*this);
    }
};

class Scalar : public Data
{
private:
    double data;
public:
    // ...
    Data* operator* (Data& data)
    {
        // Magic here - *this is now Scalar, not Data
        return data * (*this);
    }
    Scalar* operator* (Scalar &scalar)
    {
        // implement
    }

    Matrix* operator* (Matrix &matrix)
    {
        // Note how we need to allow for parameter reveral during the double dispatch
        Matrix& lhs = matrix;
        Matrix& rhs = *this;
        // Compute matrix product lhs * rhs
    }

};

I've glossed over the issue of the return type and memory management. As usual with operators, you might be better defining *= as the primitive. This can then return a reference to *this. The * operator can then defined in terms of *=. Once again, this is in "Effective C++".

小霸王臭丫头 2024-12-12 10:33:56

这个问题的解决方案称为 Double Dispatch,这在 C++ 中有点奇怪。下面的代码展示了这个技巧的工作原理:

#include <iostream>
#include <stdexcept>
#include <vector>


class Matrix;
class Scalar;

class Data {
public:
    virtual ~Data() {}
    virtual Data const& operator* (Data const& other) const = 0;
    virtual Data const& multiplyBy (Data const& other) const {
        throw std::runtime_error("bad function call");
    }
    virtual Data const& multiplyBy (Matrix const& other) const = 0;
    virtual Data const& multiplyBy (Scalar const& other) const = 0;
};

class Matrix : public Data {
private:
    std::vector< std::vector<double> > data;
public:
    virtual Data const& operator* (Data const& other) const {
        return other.multiplyBy(*this);
    }
    virtual Data const& multiplyBy (Matrix const& other) const {
        std::cout << "Matrix * Matrix" << std::endl;
        return *this;
    }
    virtual Data const& multiplyBy (Scalar const& other) const {
        std::cout << "Matrix * Scalar" << std::endl;
        return *this;
    }
};

class Scalar : public Data {
private:
    double data;
public:
    virtual Data const& operator* (Data const& other) const {
        return other.multiplyBy(*this);
    }
    virtual Data const& multiplyBy (Matrix const& other) const {
        std::cout << "Scalar * Matrix" << std::endl;
        return *this;
    }
    virtual Data const& multiplyBy (Scalar const& other) const {
        std::cout << "Scalar * Scalar" << std::endl;
        return *this;
    }
};

int
main() {
    Matrix m;
    Scalar s;
    Data* ary[] = { &m, &s };
    m * s;
    s * m;
    *(ary[0]) * *(ary[1]);
    *(ary[1]) * *(ary[0]);
    return 0;
}

The solution to this is called Double Dispatch which is a little strange in C++. The following code shows how this trick works:

#include <iostream>
#include <stdexcept>
#include <vector>


class Matrix;
class Scalar;

class Data {
public:
    virtual ~Data() {}
    virtual Data const& operator* (Data const& other) const = 0;
    virtual Data const& multiplyBy (Data const& other) const {
        throw std::runtime_error("bad function call");
    }
    virtual Data const& multiplyBy (Matrix const& other) const = 0;
    virtual Data const& multiplyBy (Scalar const& other) const = 0;
};

class Matrix : public Data {
private:
    std::vector< std::vector<double> > data;
public:
    virtual Data const& operator* (Data const& other) const {
        return other.multiplyBy(*this);
    }
    virtual Data const& multiplyBy (Matrix const& other) const {
        std::cout << "Matrix * Matrix" << std::endl;
        return *this;
    }
    virtual Data const& multiplyBy (Scalar const& other) const {
        std::cout << "Matrix * Scalar" << std::endl;
        return *this;
    }
};

class Scalar : public Data {
private:
    double data;
public:
    virtual Data const& operator* (Data const& other) const {
        return other.multiplyBy(*this);
    }
    virtual Data const& multiplyBy (Matrix const& other) const {
        std::cout << "Scalar * Matrix" << std::endl;
        return *this;
    }
    virtual Data const& multiplyBy (Scalar const& other) const {
        std::cout << "Scalar * Scalar" << std::endl;
        return *this;
    }
};

int
main() {
    Matrix m;
    Scalar s;
    Data* ary[] = { &m, &s };
    m * s;
    s * m;
    *(ary[0]) * *(ary[1]);
    *(ary[1]) * *(ary[0]);
    return 0;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文