![](/img/trans.png)
[英]How to avoid #include in header files when forward declaration causes incomplete type error?
[英]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.