簡體   English   中英

在C ++中聲明/定義類范圍常量的位置?

[英]Where to declare/define class scope constants in C++?

我很好奇C ++中不同的常量聲明和定義選項的好處/壞處。 在最長的時間內,我剛剛在類定義之前將它們聲明為頭文件的頂部:

//.h
const int MyConst = 10;
const string MyStrConst = "String";
class MyClass {
...
};

雖然這會污染全局命名空間(我知道這是一件壞事,但是從來沒有找到一個清單,說明為什么它很糟糕),常量仍將限定在各個翻譯單元中,因此不包含此標題的文件將無法訪問這些常量。 但是如果其他類定義了一個同名的常量,你就可以得到名稱沖突,這可能是一件壞事,因為它可能是一個可以重構的區域的良好指示。

最近,我決定在類定義本身內部聲明類特定常量會更好:

//.h
class MyClass {
    public:
         static const int MyConst = 10;
...
    private:
         static const string MyStrConst;
...
};
//.cpp
const string MyClass::MyStrConst = "String";

常量的可見性將根據常量是僅在類的內部使用還是使用該類的其他對象所需來調整。 這就是我現在認為最好的選擇,主要是因為你可以保持內部類常量對類是私有的,而使用公共常量的任何其他類都會有更詳細的常量來源引用(例如MyClass: :MYCONST)。 它也不會污染全局命名空間。 雖然它確實不利於在cpp文件中要求非整數初始化。

我還考慮將常量移動到它們自己的頭文件中並將它們包裝在命名空間中,以防其他類需要常量,而不是整個類定義。

只是尋找意見和可能還有其他選擇我尚未考慮過。

你聲稱將非整數常量聲明為靜態類成員“不利於要求在cpp文件中進行非整數初始化”並不完全可靠,所以說。 它確實需要cpp文件中的定義,但它不是“損害”,這是你的意圖問題。 C ++中的命名空間級const對象默認具有內部鏈接,這意味着在原始變體中聲明

const string MyStrConst = "String"; 

相當於

static const string MyStrConst = "String"; 

即它將在包含此頭文件的每個轉換單元中定義一個獨立的MyStrConst對象。 你知道嗎? 這是你的意圖嗎?

在任何情況下,如果您不需要在每個翻譯單元中特別需要單獨的對象,則在原始示例中聲明MyStrConst常量不是一個好習慣。 通常,您只在頭文件中放置一個非定義的聲明

extern const string MyStrConst; 

並在cpp文件中提供定義

const string MyStrConst = "String";

從而確保整個程序使用相同的常量對象。 換句話說,當談到非整數常量時,通常的做法是在cpp文件中定義它們。 因此,無論您如何聲明它(在課堂上或外面),您通常都必須處理必須在cpp文件中定義它的“損害”。 當然,正如我上面所說,使用命名空間常量,你可以放棄第一個變體中的內容,但這只是“懶惰編碼”的一個例子。

無論如何,我認為沒有理由使問題過於復雜:如果常量對類具有明顯的“附件”,則應將其聲明為類成員。

PS Access說明符( publicprotectedprivate )不控制名稱的可見性 他們只控制其可訪問性 在任何情況下,該名稱仍然可見。

全局命名空間的污染很糟糕,因為有人(例如您使用的庫的編寫者)可能想要將名稱MyConst用於其他目的。 這可能導致嚴重的問題(不能一起使用的庫等)

如果常量鏈接到單個類,那么第二個解決方案顯然是最好的。 如果這不是那么容易(想想物理或數學常量而沒有與程序中的類相關聯),命名空間解決方案就更好了。 順便說一句:如果你必須兼容舊的C ++編譯器,請記住其中一些不能在頭文件中使用整數初始化 - 你必須在C ++文件中初始化或在這種情況下使用舊的enum技巧。

我認為對於常數沒有更好的選擇 - 至少目前還不能想到一個......

污染全局命名空間應該是不言自明的。 如果我包含頭文件,我不想遇到或調試與該頭中聲明的常量的名稱沖突。 這些類型的錯誤確實令人沮喪,有時難以診斷。 例如,我曾經不得不鏈接一個在標題中定義的項目:

#define read _read

如果你的常量是命名空間污染,那就是命名空間核廢料。 這種情況的表現是一系列非常奇怪的編譯錯誤,抱怨錯過_read函數,但只有在鏈接到該庫時。 我們最終將讀取函數重命名為其他東西,這並不困難,但應該是不必要的。

您的第二個解決方案非常合理,因為它將變量放入范圍。 沒有必要將它與一個類相關聯,如果我需要在類之間共享常量,我將在它們自己的命名空間和頭文件中聲明常量。 這對於編譯時來說不是很好,但有時它是必要的。

我也看到人們將常量放入他們自己的類中,這可以作為單例實現。 這對我來說似乎沒有獎勵,語言為你提供了一些聲明常量的工具。

您可以在c ++文件中將它們聲明為全局變量,只要它們未在標頭中引用即可。 然后它們對該類是私有的,不會污染全局命名空間。

我個人使用你的第二種方法; 我已經用了很多年了,它對我很有用。

從可見性點開始,我傾向於使私有常量文件級靜態,因為實現文件之外的任何人都不需要知道它們存在; 如果您需要更改其名稱或添加新名稱,這有助於防止鏈式反應重新編譯,因為它們的名稱范圍與其使用范圍相同...

如果只有一個類要使用這些常量,則將它們聲明為類體內的static const 如果一堆相關類要使用常量,則將它們聲明在僅包含常量和實用程序方法的類/結構內或在專用命名空間內。 例如,

namespace MyAppAudioConstants
{
     //declare constants here
}

如果它們是整個應用程序使用的常量(或其中的大量塊),則在一個名稱空間內聲明它們(在任何地方隱式或顯式地包含)。

namespace MyAppGlobalConstants
{
    //declare constants here
}

不要污染全局命名空間,污染本地。

namespace Space
  {
  const int Pint;
  class Class {};
  };

但實際上......

class Class
  {
  static int Bar() {return 357;}
  };

暫無
暫無

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

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