2015-04-20 97 views
0

在示例代碼中,調用message()將永遠不會影響類的內容,所以我希望該方法爲const。但我不希望返回值也爲const,那麼使用const_cast如下安全嗎?還是有更好的解決方案?這是const_cast的有效用法嗎?

編輯:對不起。所以n_是一個指針!

編輯2:我終於設法正確地重新產生問題。如果n_是一個數組,如int n[100]?然後,我確實看到沒有const_cast的問題。

class A 
{ 
private: 
    int n_[10]; 

public: 
    /* ... */ 

    int* n() const 
    { 
     return const_cast<int*>(n_); 
    } 
}; 
+4

是的,但沒有必要。你沒有返回一個引用,所以調用者無法通過調用'n()'來修改'n_'。 – jxh

+1

當前的代碼試圖返回一個'int *'作爲'int'。 –

+0

現在你允許我這樣做:'const A a; int * p = a.n(); p [0] = 2;'。所以不,它根本就不安全。 – chris

回答

5

不,這不是const_cast的有效用途。

你的函數沒有修改數組,但它正在授予修改數組給調用者的權限。因此,它本身應該擁有這些權利。你不能讓某人訪問你自己無法訪問的內容。所以這個方法不應該是const的,並且const轉換是不必要的。

您可能還需要該函數的const版本,該函數返回const int*。這與原理相同,例如,std::vector::operator[]。即使運算符沒有修改向量,但它授予訪問權限來修改向量,因此它不是const函數。 (但也有一個常量重載版本,它返回一個const引用,因此不授予修改向量的權利)

7

返回一個類型(而不是引用)將使複製你返回對象的。因此不需要施放它,副本可以在不影響原始的情況下進行更改。如果您刪除了const_cast,代碼將會乾淨地編譯。

編輯:基於最新編輯的問題,我會說這是一個濫用const_cast。 C++遵循的原則是const成員函數不僅不應該對對象本身做任何更改,而且不應該返回任何可用於在函數外進行更改的內容。通過返回一個非const指針給成員變量,你違反了這個原則。

+0

在該函數的上下文中,不是'n_'隱式'const'? – tadman

+0

你能看到我的編輯?我在原帖中犯了一個很大的錯誤。 – xiver77

+0

@tadman是的,但你可以毫無困難地創建一個'const'變量的副本。 –

0

你可以只返回n_,因爲它是

int n() const 
{ 
    return n_; 
} 
0

沒有必要使用石膏。在該函數中,this->n_是一個const指針,它不指向const int

int* n() const 
{ 
    // No need for a cast. 
    return n_; 
} 

它更有意義,從const函數返回一個const int*。你不希望這樣的事情:

const A a; 
a.n()[0] = 10; 

這顛覆了const -ness的對象。您可以通過使用以下方法來防止這種情況:

const int* n() const 
{ 
    // No need for a cast either. 
    return n_; 
} 
0

一般而言,將T const轉換爲Tconst_cast<>幾乎總是不必要的。這是因爲常量對象正在轉換爲非常量臨時對象,並且這可以在沒有強制轉換的情況下安全地完成。

int const n; // n is a constant int 
int x = n;  // perfectly safe 

即使T是指針類型也是如此。

int * const n; // n is a constant pointer to an int 
int * x = n; // perfectly safe 

但是,如果移動const關鍵字前,它不再是使得指針類型不變,但被指向到常量的類型。因此,我們上面的例子:

const int * n; // n is a pointer to a constant int 
int * x = n // error, x is a pointer to an int 

你可以看到,x點,比n點不同的東西,所以初始化失敗。在這種情況下,初始化將需要const_cast<>

int * x = const_cast<int *>(n); 
       // cast away the const-ness that n is pointing to 

你只能這樣做,如果你知道n實際上是modifyable(它可能不是如果指針是實際只讀存儲器),或者如果您知道x的用戶實際上不會嘗試修改n指向的內容。


對於你的榜樣,你似乎認爲你const方法應該返回一個指針,以這樣一種方式,該數據是由調用者修改你的對象保存數據。也就是說,由於n()方法被聲明爲const,這意味着被訪問對象的內容應該被視爲常量。因此,n_是一個常數爲int的數組,它將衰減爲指向常量int的指針,但您要返回指向int的指針。

如果您打算n_是可修改的,無論該對象是否被視爲常量,您可以使用mutable聲明該意圖。這將使n_被視爲非常量,即使包含對象是const,並且它因此使const_cast不必要。

class A 
{ 
private: 
    mutable int n_[10]; 

public: 
    /* ... */ 

    int* n() const 
    { 
     return n_; 
    } 
};