簡體   English   中英

* static *成員函數的const和非const版本

[英]const and non-const versions of *static* member functions

我有兩個版本的相同的靜態成員函數:一個采用指向const的指針參數,並采用指向非const的參數。 我想避免代碼重復。
在閱讀了一些堆棧溢出問題(這些都是關於非靜態成員函數的)之后我想出了這個:

class C {
private:
  static const type* func(const type* x) {
    //long code
  }

  static type* func(type* x) {
      return const_cast<type*>(func(static_cast<const type*>(x)));
  }
public:
  //some code that uses these functions
};

(我知道玩指針通常是一個壞主意,但我正在實現一個數據結構。)

我在libstdc ++中發現了一些代碼如下:
注意:這些不是成員函數

static type* local_func(type* x)
{
  //long code
}

type* func(type* x)
{
  return local_func(x);
}

const type* func(const type* x)
{
  return local_func(const_cast<type*>(x));
}

在第一種方法中,代碼在一個帶有指針到const參數的函數中。
在第二種方法中,代碼在一個函數中,該函數接受指向非const的參數。
通常應該使用哪種方法? 兩個都正確嗎?

最重要的規則是接口函數(公共方法,詳細命名空間中的一個以外的自由函數等)不應拋棄其輸入的常量。 Scott Meyer是第一個談論使用const_cast防止重復的人之一,這是一個典型的例子( 如何刪除類似的const和非const成員函數之間的代碼重復? ):

struct C {
  const char & get() const {
    return c;
  }
  char & get() {
    return const_cast<char &>(static_cast<const C &>(*this).get());
  }
  char c;

};

這是指實例方法而不是靜態/自由函數,但原理是相同的。 您注意到非const版本添加了const來調用另一個方法(對於實例方法, this指針是輸入)。 然后它最后拋棄了constness; 這是安全的,因為它知道原始輸入不是const。

反過來實現這一點非常危險。 如果你拋棄你收到的函數參數的constness,如果傳遞給你的對象實際上是const,你在UB中冒了很大的風險。 也就是說,如果你調用任何實際改變對象的方法(現在你已經拋棄const就很容易做到),你可以輕松獲得UB:

C ++標准,第5.2.11 / 7節[const cast]

[注意:根據對象的類型,通過指針,左值或指向數據成員的指針的寫入操作會導致const-qualifier的const_cast,這可能會產生未定義的行為。 - 尾注]

它在私有方法/實現函數中並沒有那么糟糕,因為你可能會仔細控制它被調用的方式/時間,但為什么這樣做呢? 沒有任何好處更危險。

從概念上講,通常情況下,當你有一個相同函數的const和非const版本時,你只是傳遞對象的內部引用( vector::operator[]是一個規范的例子),而不是實際上是在改變任何東西,這意味着你寫它的方式都是安全的。 但拋棄輸入的常量仍然更危險; 雖然你可能不太可能弄亂自己,想象一個團隊設置,你用錯誤的方式寫它並且工作正常,然后有人改變實現以改變某些東西,給你UB。

總之,在許多情況下,它可能沒有實際的區別,但是有一種正確的方法可以做到這一點,它比替代方案更好: constness 添加輸入中 ,並從輸出中 刪除 constness。

我以前只見過你的第一個版本,所以根據我的經驗,這是更常見的習語。

第一個版本對我來說似乎是正確的,而第二個版本可能會導致未定義的行為,如果(A)您將實際的const對象傳遞給函數和(B) long code寫入該對象。 鑒於在第一種情況下,編譯器將告訴您,如果您嘗試寫入對象,我將永遠不會推薦選項2。 您可以考慮使用/返回const的獨立函數。

暫無
暫無

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

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