簡體   English   中英

僅C ++頭文件項目-在不同程序集中使用

[英]C++ header file only project - use from different assembly

我有一個項目必須更改,從將.cpp / header文件分離到將定義僅合並到頭文件中。 我最初嘗試將cpp文件的內容復制到頭文件中,但是我的想法-VS2012 express-使我陷入一個循環,其中說頭文件包含自身,因此當我刪除include“ class.h”時,它抱怨說如果是Class :: functionname,則無法識別該Class。 最終我決定在標題本身中定義定義,例如

class Thing {
public:
   void func { code; } 
}

這解決了我在項目上的編譯問題。 問題是我有一個測試項目-WinUnit-我無法再訪問這些功能。 該項目以前是一個靜態庫,因此進行了鏈接,但是由於沒有.cpp文件,因此該項目沒有生成.lib。 嘗試更改為動態鏈接庫,相同的問題-未生成dll。 因此,我添加了一個項目引用,並且似乎可以通過鍵入#include“ Class.h”來識別我的類文件。

我的問題是它仍然無法編譯類。 它根本無法識別測試項目的.cpp文件中的類名稱。 我什至嘗試將頭文件添加到測試項目中,但仍然不滿意。 我嘗試將“其他包含目錄”設置為指向標頭所在的位置-不好。

我該怎么做?

編輯:仍然卡住,所以我創建了一個SSCCE,它工作正常,將測試項目指向Additonal INclude目錄中的頭文件目錄,並且它可以工作。 盡管主項目可以正常編譯,但我注意到它存在一個智能錯誤-標識符“ ClassName”未定義。 所有其他班級都認可其他班級。 #include“ className”存在。 當我構建測試項目時,第一個錯誤與該行相關,並帶有智能感知錯誤:錯誤1錯誤C2143:語法錯誤:缺少';' 在“ *”之前

實際的行是:ClassName * obj; -這是一個私有變量。

測試項目中有629個錯誤-其他一些代碼:c4430,c2061。 我想這些僅僅是與無法識別的班級相關的最初問題的副作用...迷路了,可能會退縮並重新思考失敗的問題...。

編輯:修復了智能錯誤,現在所有錯誤都在Testproject中-上升到826個錯誤。 包含頭文件時查看,但無法識別任何類名。 錯誤代碼:c2061,c2065,c2923等

在示例代碼中, func是私有的,因為這是類內部的默認訪問權限。 也許您想定義公共函數,以便您的測試代碼和該類的其他客戶端可以訪問。

如果僅將函數定義放在標頭中,則還必須使它們內聯。 顯式(對於自由函數和完全專用的函數模板定義),或隱式(即在類定義內定義類方法)。

您是對的,因為該庫不再產生任何已編譯的輸出,即您不必鏈接lib文件或dll文件。 因此,在使用該庫的任何項目(包括您的測試項目)中,您都不再需要指定要與該項目鏈接的庫。 畢竟,這就是僅頭文件庫的原因之一:它們在編譯時(而不是鏈接時)被完全包含在內。

如果您的測試項目是在之前編譯的,則它也應該在修改后進行編譯,前提是您之前已測試了所有庫類,並且未對名稱空間結構進行任何更改。

如果沒有SSCCE以及您從編譯器中得到的適當錯誤,人們只能猜測可能會遇到的其他陷阱。

編輯:想到的一件事即使是正確完成了源到標題的重構,也可能引起麻煩的是循環包含。 如果有這些,則必須打破依賴關系或將兩個類放入同一標頭,在兩個類定義之后都提供方法定義(請記住要顯式內聯地聲明方法定義)

Edit2:圓形包含的簡單示例:類A和B都具有調用另一個類的方法的方法。 因此,每個類方法的定義都需要聲明其他類的方法,即,僅對其他類進行前向聲明是不夠的。 在正常情況下,源將同時包含兩個標頭並完成操作。 在僅標頭的情況下,編譯器將如下所示:

class A {
  B* b_;
public:
  A(B* b) : b_(b) {}
  void foo() {b_->meow();}
};

class B {
public:
  void bar() { A a(this); a.foo(); }
  void meow() { /* ... */}
};

編譯器會抱怨B的用法以及對B::meow()的調用。 前者可以通過向前聲明B來解決,后者則不能。 首先定義B將無濟於事,A和A::foo()會遇到相同的問題。 因此,解決方案必須如下所示:

class A {
  B* b_;
public:
  A(B* b) : b_(b) {}
  void foo();   //1
};

class B {
public:
  void bar() { A a(this); a.foo(); }
  void meow() { /* ... */}
};

inline void A::foo() {b_->meow();} //2

依賴於第二類的第一類方法的定義可以延遲到第二類的定義之后。 由於A需要B,而B需要A,因此在僅標頭的庫中將這樣混合的類定義分隔在兩個不同的標頭中幾乎沒有意義。

分離此類事物的一種方法是打破依賴關系。 在上述情況下,可能看起來像這樣:

class B_Interface
{
public: 
  virtual void meow() = 0;
};

class A {
  B_Interface* b_;
public:
  A(B_Interface* b) : b_(b) {}
  void foo() {b_->meow();} //OK this time
};

class B : public B_Interface {
public:
  void bar() { A a(this); a.foo(); }
  virtual void meow() { /* ... */}
};

這是以另外一個間接為代價的,但是將兩個類的依賴關系分開,使對A等的測試更加容易。

我受夠了,由於某種原因它仍然無法工作,這已經浪費了我的時間和精力。 我回到了一個結構良好的項目,只剩下標題了。

暫無
暫無

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

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