当对象是指针时重载 == 和 !==

Overloading == and !== when object is a pointer

我是编写运算符的新手(在本例中为 ==!=)。我做了一些研究,到目前为止想出了:

bool operator==(const SPECIAL_EVENT_S &rsEvent)
{
    bool bSame = false;

    if (rsEvent.datEvent == m_datSpecialEvent &&
        rsEvent.strEvent == m_strNotes &&
        rsEvent.strLocation == m_strLocation &&
        rsEvent.datEventStartTime == m_datEventStartTime &&
        rsEvent.datEventFinishTime == m_datEventFinishTime &&
        gsl::narrow<bool>(rsEvent.bEventAllDay) == m_bEventAllDay &&
        gsl::narrow<bool>(rsEvent.bSetReminder) == m_bSetReminder &&
        rsEvent.iReminderUnitType == m_iReminderUnitType &&
        rsEvent.iReminderInterval == m_iReminderInterval &&
        rsEvent.iImageWidthPercent == m_wImageWidthPercent &&
        rsEvent.strImagePath == m_strImagePath &&
        rsEvent.strTextBeforeImage == m_strTextBeforeImage &&
        rsEvent.strTextAfterImage == m_strTextAfterImage &&
        rsEvent.eType == m_eVideoconfType &&
        rsEvent.sBSSTI == m_sBSSTI)
    {
        // The fundamental information is unchanged
        bSame = true;
    }

    // Now compare the MWB Event Type
    if (bSame)
    {
        switch (rsEvent.eMWBEventType)
        {
        case EventTypeMWB::MWBBethelSpeakerServiceTalk:
            return m_bSpecialEventBethelServiceTalk;
        case EventTypeMWB::MWBVideoconferenceAssembly:
            return m_bSpecialEventVideoconf && m_eVideoconfType == VideoConferenceEventType::Live;
        case EventTypeMWB::MWBVideoconferenceConvention:
            return m_bSpecialEventVideoconf && m_eVideoconfType == VideoConferenceEventType::Recorded;
        case EventTypeMWB::MWBSpecialEvent:
            return m_bSpecialEvent;
        case EventTypeMWB::MWBMemorial:
            return m_bEventMemorial;
        case EventTypeMWB::MWBCircuitOverseerMeeting:
            return m_bCircuitVisit || m_bCircuitVisitGroup;
        case EventTypeMWB::MWBMeeting:
            return !m_bNoMeeting;
        default:
            bSame = false;
        }
    }

    return bSame;
}
bool operator!=(const SPECIAL_EVENT_S& rsEvent)
{
    return !(rsEvent == *this);
}

当我尝试使用这些运算符时,令我感到惊讶的是:

if (pEntry != sEvent)
{
    AfxMessageBox(_T("The special event information has changed"));
}

它不喜欢 pEntry 作为指针。最后我这样做了:

if (*pEntry != sEvent)
{
    AfxMessageBox(_T("The special event information has changed"));
}
  1. 为什么这首先是一个问题?我这么问是因为如果这是一个标准函数,那么对象是不是指针都没有关系。
  2. 迎合这种情况的正确方法是什么?

例如:

Function 当它是/不是指针时,它可以被对象使用。那么为什么不用 operator?

Function can be used both by the object when it is / is not a pointer.

事实上,不,它不能。在像 object->Function(value) 这样的 statement/expression 中,->(成员访问)和 ()(函数调用)运算符具有 same precedenceleft-to-right结合性。因此,首先应用 -> 并自动解除对指针的引用。因此,效果与 (*object).Function(value) 相同 – 而 Functionstillobject 上被调用,而不是在指针上。

So why not with an operator?

调用operator函数的语法是(或者可以)相当不同:因为它被定义为运算符,您可以使用运算符标记(在两个操作数之间)调用它,而不是使用显式函数调用。但是,你 必须 传递对象,因为这就是操作数的定义。

但是,如果您真的想要,您 可以 仍然使用显式 function-call 语法调用运算符覆盖;并且,在这种情况下,您可以在指针上使用 -> ;像这样(其中 operator== 实际上是函数的 'name'):

if (!pEntry->operator==(sEvent))
{
    AfxMessageBox(_T("The special event information has changed"));
}

然而,这似乎是一项艰巨的工作,而您的 *pEntry != sEvent 实际上是 'correct' 使用覆盖的方式。


PS:作为奖励,如果您使用的编译器支持 C++20(或更高版本)标准,您可以在 structures/classes 中添加 "defaulted" operator== ,这将节省您显式比较每个单独的数据成员的时间:

struct foo {
    int a;
    double b;
    bool operator==(const foo&) const = default; // Compares "a" and "b"
};

struct bar {
    foo f;
    int c;
    int d;
    bool operator==(const bar&) const = default; // Compares "c", "d" and "f"
};