簡體   English   中英

C++ 不同類型的對稱二元運算符

[英]C++ Symmetric Binary Operators with Different Types

我正在學習 C++,我想知道是否可以深入了解創建適用於兩種不同類型實例的二元運算符的首選方法。 這是我為說明我的擔憂而做的一個例子:

class A;
class B;

class A
{
    private:
        int x;

    public:
        A(int x);

        int getX() const;

        int operator + (const B& b);
};


class B
{
    private:
        int x;

    public:
        B(int x);

        int getX() const;

        int operator + (const A& A);
};


A::A(int x) : x(x) {}

int A::getX() const { return x; }

// Method 1
int A::operator + (const B& b) { return getX() + b.getX(); }


B::B(int x) : x(x) {}

int B::getX() const { return x; }

// Method 1
int B::operator + (const A& a) { return getX() + a.getX(); }


// Method 2
int operator + (const A& a, const B& b) { return a.getX() + b.getX(); }

int operator + (const B& b, const A& a) { return a.getX() + b.getX(); }


#include <iostream>

using namespace std;

int main()
{
    A a(2);
    B b(2);

    cout << a + b << endl;

    return 0;
};

如果我想在這兩種類型之間具有對稱性,那么在上面的代碼中哪種方法是最好的方法。 選擇一種方法而不是另一種方法是否有任何可能的危險? 這是否因返回類型而異? 請解釋! 謝謝!

最好的方法是定義(在任一類之外) int operator+ (const A& a, const B& b) ,並在需要時使其成為兩個類的朋友 function。 此外,定義

int operator+(const B& b, const A& a) {return a + b;}

使其對稱。

這種方法的最大風險是人們傾向於將 + 視為對稱運算符。 這是寫的方式,它不是(除非你的實現是相同的)。

至少,您應該將 + 作為外部二元運算符(而不是成員)重載,然后多次重載它。

但是,您必須小心,以確保沒有任何事情變得模棱兩可。

你能解釋一下你想做什么嗎? 我想不出有很多不同類型的情況下,擁有對稱異構運算符是有意義的。

方法 2 的主要論點是您可以在兩個操作數上進行隱式類型轉換,而不僅僅是第二個。 這可能會在某個地方避免混亂。

說到這一點,您的示例代碼通過兩個類上的 1-arg 構造函數定義了從 int 到 A 和從 int 到 B 的隱式轉換。 這可能會導致以后產生歧義。 但是,如果您為了簡潔而省略了“顯式”,那就足夠了。

不過,我同意 Uri 的警告:如果您發現自己這樣做,您可能正在編寫 API,其他人會感到困惑。 為什么 A 加 B 是 int ? 添加 a 和 b,而不是自己調用 getX 並添加結果,真的讓用戶更容易嗎?

是因為用戶非常清楚 A 和 B 是整數的包裝器嗎? 如果是這樣,那么另一種選擇是通過運算符 int() 公開從 A 到 int 和從 B 到 int 的轉換。 然后 a+b 將出於合理的原因返回一個 int ,並且您還將獲得所有其他算術運算符:

#include <iostream>

struct A {
    int x;
    explicit A(int _x) : x(_x) {}
    operator int() {
        return x;
    }
};

struct B {
    int x;
    explicit B(int _x) : x(_x) {}
    operator int() {
        return x;
    }
};

int main() {
    A a(2);
    B b(2);
    std::cout << a + b << "\n";
    std::cout << a - b << "\n";
}

我在評論中讀到您的預期用途是添加向量和矩陣。 也許你應該考慮只使用向量是一維矩陣的矩陣。 然后你只剩下一種類型和一組運算符:

matrix operator*( matrix const& a, matrix const& b );
matrix operator+( matrix const& a, matrix const& b ); // and so on

如果要保留向量 class 那么您應該考慮是否還需要轉置向量(也許轉置只是向量的內部屬性)。

這組操作並不是真正對稱的:

 vector * matrix = vector matrix * vector_t = vector_t matrix * matrix = matrix vector_t * vector = matrix vector * vector_t = int

並且您應該提供這三個操作(假設轉置是向量的屬性):

vector operator*( vector const& v, matrix const& m );
vector operator*( matrix const& m, vector const& v );
matrix operator*( matrix const& m1, matrix const& m2 );
matrix operator*( vector const& v1, vector const& v2 ); // possibly 1x1 matrix, you cannot overload changing only return value

如果可能,所有功能都是免費的。 即使上面的集合不是對稱的,現實世界也不是對稱的,你的用戶會期望它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM