簡體   English   中英

標頭中類的前向聲明導致類型不完整

[英]Forward declaration of class in header causes incomplete type

我看了看前向聲明,以避開編譯錯誤“錯誤:變量或字段'mov_avg'聲明為空”。
下面的場景:有一個data_proc.cpp具有main(),其中包括一個自定義標頭my_mov_avg.h ,該標頭嵌入了功能mov_avg(shared) 此外,頭函數訪問主文件中的class cl_shared 這些文件如下所示:

#include <string.h>     //c++ headers
#include <iostream> //red?

#include "my_mov_avg.h" //outsourced function

using namespace std;

/* class accessed from header*/
class cl_shared {
public:
    //constructor 
    cl_shared() { };

    int getint() {
        return a;
    }
private:
    int a;
};
cl_shared shared; //class object

/*main calling function inside header*/
int main(int argc, char **argv){
    mov_avg(shared);
    getchar();
    return 0;
}

頭文件my_mov_avg.h

//in .h
void say();
void mov_avg();

//in .cpp
#include <string.h>     
#include <iostream> 
#include "my_mov_avg.h"


void say() {
    std::cout << "Ohai from another .cpp file!";
}
class cl_shared; //Forward declaration
void mov_avg(cl_shared shared){
        std::cout<<" int from class: "<< shared.getint()<< std::endl; 
}

現在,當我向前聲明以定義函數參數類型時,出現了此編譯錯誤:

 error: ‘shared’ has incomplete type
 void mov_avg(cl_shared shared){
      ^
 /my_mov_avg.cpp:9:11: error: forward declaration of ‘class cl_shared’
 class cl_shared;
       ^

如何獲取它進行編譯,從頭文件訪問類cl_shared是否設計不好?
我試圖實現的目標是從調用標頭函數的位置重復訪問數據(此處細分為變化的int)。
我可以將class cl_shared分解為一個單獨的頭文件,並將其包含在兩個頭文件中,但是我不確定,此外,它還會導致另一個頭文件(可能沒有必要)。
編輯在my_mov_avg.h內添加了參數
void mov_avg(cl_shared shared); 但仍然會導致:

my_mov_avg.h:3:14: error: variable or field ‘mov_avg’ declared void
 void mov_avg(cl_shared shared);

旁注:分解一個大的cpp文件的一種快速而骯臟的技巧是將函數放置在單獨的cpp中,並將#include "seperate.cpp"放置在該函數最初所在的位置。 僅用於簡單程序。

僅當您使用類作為指針/引用並且不嘗試訪問其任何成員時,前向聲明才起作用。 當您按值傳遞時,編譯器需要知道確切的大小。 類型,因此需要完整的類聲明。

void mov_avg(cl_shared shared){

在這里,您按值傳遞(即您在堆棧上傳遞共享的副本),因此編譯器需要完整的類聲明。 同樣,當您訪問類的成員時,切換到通過指針/引用傳遞是不夠的,因為編譯器將需要知道類成員的內存布局。

在使用它之前,需要聲明my_mov_arg.h可以訪問它的某個地方的cl_shared。

在副音上,當您在標頭中聲明非類成員函數(例如mov_arg)時,應將它們聲明為內聯。 否則,函數定義將被添加到您在其中使用標頭的每個源文件中,並導致編譯錯誤。

編輯。 這應該做。 如果需要,還可以將成員函數從cl_shared.h移到cl_shared.cpp文件中。 標頭文件頂部的#pragma一次是為了確保每個編譯單元僅包含一次標頭:

cl_shared.h:

#pragma once

class cl_shared {
    public:
    //constructor 
    cl_shared() { };

    int getint() {
        return a;
    }
private:
    int a;
};

my_mov_avg.h

#pragma once
#include "cl_shared.h"

void say();
void mov_avg(cl_shared shared);

如果頭文件僅包含

void mov_avg();

那么這將是另一種功能-不帶參數的功能。 C ++強烈類型化函數-重載可以具有不同的參數簽名但名稱相同。 因此,它看到了move_avg()的聲明,但沒有move_avg(cl_shared shared)

暫無
暫無

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

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