簡體   English   中英

如何從 const 方法調用非常量方法?

[英]How to call a non-const method from a const method?

我的類中有一個 const 方法,它不能更改為非常量。 在這種方法中,我需要調用一個非常量方法,但編譯器不允許我這樣做。

有什么辦法可以解決嗎? 這是我的代碼的簡化示例:

int SomeClass::someMethod() const {
    QColor saveColor = color();
    setColor(QColor(255,255,255)); // Calling non-const method

    // ....

    setColor(saveColor); // restore color

    return 1;
}

你可以在this指針上使用const_cast

int SomeClass::someMethod() const {
    const_cast<SomeClass*>( this )->setColor(...);// Calling non-const method
    //whatever
}

但是如果你對一個最初聲明為const的對象這樣做,你會遇到未定義的行為。

所以這:

SomeClass object;
object.someMethod();

沒關系,但是這個:

const SomeClass object;
object.someMethod();

產生未定義的行為。

真正的解決方案是您的const函數首先不應該是const

如果您需要更改const方法內的某些內部狀態,您還可以聲明受影響的狀態mutable

class Foo {
public:
    void doStuff() const { bar = 5; }
private:
    mutable int bar;
};

這適用於您將互斥鎖之類的東西作為類成員的情況。 獲取和釋放互斥鎖不會影響客戶端可見的狀態,但在const方法中在技術上是禁止的。 解決方案是將互斥鎖標記為mutable 您的情況看起來很相似,但我認為您的課程需要進行一些重構才能使此解決方案適用。

此外,您可能想閱讀此答案以了解如何使用 RAII 使此臨時狀態更改異常安全。

const正確性的挑戰之一是你不能半途而廢。 要么全有,要么全無。 如果你嘗試半途而廢,你最終會陷入困境,就像你在這里一樣。 你最終會得到一個不錯的const -correct 類,它被一些瘋狂的舊的、典型的遺留(或由一個舊的脾氣暴躁的人編寫)代碼使用,這些代碼不是const正確的,它只是不起作用。 你會想知道const正確性是否值得所有的麻煩。

I need to call a non-const method [from a const method]

你不能——不能直接。 你也不應該。 但是,還有一種替代方法......

顯然,你不能調用非const從方法const方法。 否則,當應用於成員函數時, const將毫無意義。

const成員函數可以更改標記為mutable成員變量,但您已經指出這在您的情況下是不可能的。

您可以嘗試通過執行SomeClass* me = const_cast<SomeClass*>(this);類的操作來擺脫constSomeClass* me = const_cast<SomeClass*>(this); 但是 A) 這通常會導致 UB,或 2) 它違反了const正確性的整個想法。

如果您真正想要完成的事情支持這一點,您可以做的一件事是創建一個非const代理對象,並使用它執行非const -y 的事情。 以機智:

#include <iostream>
#include <string>
using namespace std;

class Gizmo
{
public:
    Gizmo() : n_(42) {};
    void Foo() const;
    void Bar() { cout << "Bar() : " << n_ << "\n"; }
    void SetN(int n) { n_ = n; };
    int GetN() const { return n_; }
private:
    int n_;
};

void Gizmo::Foo() const
{
    // we want to do non-const'y things, so create a proxy...
    Gizmo proxy(*this);
    int save_n = proxy.GetN();
    proxy.SetN(save_n + 1);
    proxy.Bar();
    proxy.SetN(save_n);
}

int main()
{
    Gizmo gizmo;
    gizmo.Foo();
}

如何從 const 方法調用非常量方法?

你不應該。 如果您使用const_cast拋棄this的常量性,您可能會遇到未定義的行為。 const_cast的使用會使編譯器閉嘴,但這不是解決方案。 如果你需要這樣做,那么這意味着 const 函數首先不應該是const 使它成為非常量。

或者,您應該做一些其他事情,這不需要您從const函數調用非常量函數。 比如,不要調用setColor函數? 比如,將 const 函數拆分為多個函數(如果可以的話)? 或者是其他東西?

在您的特定情況下,如果setColor僅設置一些成員變量,例如m_color ,那么您可以將其聲明為mutable

 mutable QColor m_color;

然后在您的 const 函數中設置它,而不調用setColor函數,也不執行const_cast

暫無
暫無

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

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