簡體   English   中英

對 C++ 類的使用感到困惑

[英]Confused about C++ class usage

以下是讓我對 class 的用法有些困惑的代碼。

    template <int dim>
    class FEM
    {
    public:
      FEM (unsigned int order,unsigned int problem); 
      ~FEM(); 
    ...
    FESystem<dim>        fe;
    DoFHandler<dim>      dof_handler;
    ...
    }

    template <int dim>
    FEM<dim>::FEM(unsigned int order,unsigned int problem)
    :
    fe (FE_Q<dim>(order), dim), 
    dof_handler (triangulation)
    {
    ...
    }

這里的“FESystem”、“DoFHandler”和“FE_Q”是頭文件中的一些預定義類。 我對這段代碼有幾個問題:

(1)為什么構造函數“fe”和“dof_handler”在類“FE”本身之外聲明,是否有可能在第一個括號內,即在“FE”類定義內聲明它們?

(2)代碼中的雙冒號和冒號“ :: ”和“ : ”分別是什么意思? 為什么在這里使用它們? 冒號“:”是否表示繼承?

    template <int dim>
    FEM<dim>::FEM(unsigned int order,unsigned int problem)
    :
    fe (FE_Q<dim>(order), dim), 
    dof_handler (triangulation){...}

我是 C++ 新手。 誰能給我一些幫助? 太欣賞了!

雙冒號用於指定您正在為特定類實現函數。 在本例中,它是 FEM 類的構造函數的實現。 如果 FEM 有一個方法 DoIt(),則實現可能如下所示:

template<int dim>
int FEM<dim>::DoIt() { return 1; }

如果要將參數直接傳遞給成員變量的構造函數,則單冒號“:”與構造函數一起使用。 所以在上面的代碼中,FEM 的構造函數正在將參數傳遞給它的成員fe FESystem 必須有一個構造函數,它接受一個 FE_Q << dim >> 和一個 int 作為參數。 它也在向 DoFHandler 傳遞一些東西,但不清楚代碼中的triangulation是什么。 這看起來不會編譯。

(1)為什么構造函數“fe”和“dof_handler”在類“FE”本身之外聲明,是否有可能在第一個括號內,即在“FE”類定義內聲明它們?

是的,對於模板化類,它們可以位於“FE”模板類定義的內部或外部。 有些人更喜歡它們的可讀性,在那里他們可以看到每個可用功能的列表,而不必向下滾動太多。

但是,對於常規的非模板化類,請將您的類外實現放在相應的源 ( .cpp ) 文件中,而不是在類下方或類中。 原因是,包含您的頭文件的所有其他類都將一遍又一遍地編譯相同的實現,這將減慢您的構建速度並生成大量二進制文件。 對於模板化類,您別無選擇。 它們必須由每個翻譯單元編譯,因為模板化將由您的編譯器生成代碼。

(2)代碼中的雙冒號和冒號“::”和“:”分別是什么意思? 為什么在這里使用它們? 冒號“:”是否表示繼承?

雙冒號是你的范圍。 它可以是命名空間或類名。 這使得可以從兩個不同的類中命名完全相同的 2 個函數而不會發生名稱沖突。 它對於覆蓋非常有用。

例如,您可以在標題中包含此內容:

class A
{
public:
    virtual foo(int a);
};

class B : public A
{
public:
    virtual foo(int a);
};

並將其放在您的源 ( .cpp ) 文件中:

A::foo(int a) {
    printf("Hello World from A::foo(%s)\n", a);
}

B::foo(int a) {
    A::foo(a); // calling the super class's foo(int)
    printf("Hello World from B::foo(%s)\n", a);
}

如果我們沒有作用域,我們將無法區分這兩個函數。 在 Java 或 C# 中,這已被簡化為一個點。

這種特殊情況下的單冒號是 C++ 構造函數的一個非常特殊的特性。 只有構造函數可以做到這一點。 這稱為“初始化程序”,它們是一種巧妙的小優化,可用於比在構造函數范圍內手動設置成員變量的默認值更快。

例如,如果你在這里有這個類:

class A
{
public:
    A(); // constructor

    int a;
    float b;
};

您可能希望在.cpp源文件中像這樣編寫構造函數:

A::A() {
    a = 0;
    b = 0.0;
}

但是,通過初始化,您可以這樣編寫:

A::A() :
    a(0),
    b(0.0)
{
}

據說它們可以更快地初始化您的內存,只要您以與它們在標頭中聲明的順序相同的順序初始化它們。 在這個特殊的例子,如果你初始化ba ,優化將無法正常工作。

C++ 一開始可能很難理解,但它是一種非常強大的語言,學習起來真的很有趣。

C++ 中的類方法通常在類定義之外定義。 這與 Java、Python 等不同。它有一個很好的理由:類的定義只包含其方法的原型,即所謂的聲明。 這是程序其他部分了解特定類的外觀所需的所有信息。 類定義保存在頭文件中。 並且這些頭文件需要包含在使用該類的每個源代碼中。

方法的實際實現通常保存在單獨的文件中。 因此,類名和它前面的雙冒號來標識它們所屬的類。

頭文件中的源代碼將與使用這些類定義的每一段代碼一起編譯。 方法背后的實際程序可以單獨編譯,並在鏈接階段添加。

暫無
暫無

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

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