第六十五篇:VS工程檔案中cpp、h檔案在main中呼叫關係及如何避免出現“找到一個或多個多重定義的符號”
作者:liaojiacai 郵箱: [email protected]
1、出現的問題:”error LNK1169: 找到一個或多個多重定義的符號“的錯誤
2、該問題出現的場景:(假設有一個A.h,A.cpp,main,在main中呼叫了A.cpp檔案中的函式,A.cpp檔案中的部分變數是在A.h檔案中宣告的)
有多個cpp檔案和與之對應的h檔案,在main中呼叫這些檔案時候需要包含進去,cpp檔案中有包含h檔案,main函式中也有h檔案,當h檔案中有定義的共有類時會出現這個問題,就是編譯的時候出現重定義,之所以出現這個問題,是因為凡是包含h標頭檔案的地方,都會執行一遍h檔案裡面的內容,cpp檔案和main中都包含h檔案,都會編譯,這樣誰先編譯,那麼等到編譯另外一個檔案的時候,h檔案裡面的東西都有了,再編譯就會檢查出重定義了,但是不包含h檔案,那麼h檔案對應的cpp檔案中的函式不能直接在main中使用,必須加extern,cpp檔案不包含h檔案,那麼h檔案中的部分變數沒辦法在cpp檔案中定義
3、解決方法:
重定義主要是標頭檔案重複包含反覆編譯了
最直接的解決方法就是:
以head.h檔案為例,head.h檔案在head.cpp和main.cpp標頭檔案中都包含了這樣重複編譯就會出錯,解決方法如下:
在有包含用到head.h的檔案中最前面新增
#if !define(HEAD_H)
#define HEAD_H
其實就是C++程式設計的基礎知識,當然對沒有系統學習過C++的,肯定是一臉懵逼!!!
智慧的網友給出了很多的解決方法,也放在下面:
方法1、參見部落格
這是基本的解決方法,就是把h檔案中只放cpp檔案中函式的宣告,h中定義的變數都放在cpp檔案的開頭,cpp檔案中不用包含h標頭檔案,main中包含h標頭檔案就OK了!!!
方法2、可以在VS裡面設定強制編譯
忽略這個問題這個方法也可行但是感覺很彆扭,隱隱約約感覺到有問題,即使出了結果,感覺總有點不舒服,這種方法就是預設這裡找到的同名的函式是一個,即兩次編譯的h檔案是一個,忽略後面編譯的一次
方法3、(其實不是方法,這是c++的標準規範的呼叫)
上面的兩種辦法的根本是沒有搞清楚編譯的過程,說白了就是沒有搞清楚h檔案,cpp檔案,main檔案之間的相互依賴關係,方法1會出現這樣的問題,當我在h檔案中宣告的函式的引數中有在cpp檔案中定義的類的時候,這種方法無解,因為方法1講cpp檔案需要的定義都放在cpp檔案開始部分,h檔案中宣告的函式的引數又有cpp檔案中定義的類,這樣等等話,h檔案中對函式申明失敗,找不到使用了在cpp檔案中定義的引數。如果在cpp檔案和h檔案中都聲明瞭同一個類,這樣h檔案中宣告帶有這個類的引數的函式時候不會出現問題,但是h檔案和cpp檔案中都定義了同一個類,這明顯重定義了。
正確的使用方法是:
下面舉例子
1)main裡面:
#include"Feature_Triangulate_3D_rebuild3.h"
2)Feature_Triangulate_3D_rebuild3.cpp裡面:
#include"Feature_Triangulate_3D_rebuild3.h"
3)Feature_Triangulate_3D_rebuild3.h裡面
#include"common.h"
bool TestTriangulation(const vector<CloudPoint>& pcloud, const Matx34d& P, vector<uchar>& status);
4)common.h裡面
struct CloudPoint {
cv::Point3d pt;
std::vector<int> imgpt_for_img;
double reprojection_error;
};
std::vector<cv::Point3d> CloudPointsToPoints(const std::vector<CloudPoint> cpts);
5)common.cpp裡面
#include"common.h"
std::vector<cv::Point3d> CloudPointsToPoints(const std::vector<CloudPoint> cpts)
{
std::vector<cv::Point3d> out;
for (unsigned int i = 0; i<cpts.size(); i++)
{
out.push_back(cpts[i].pt);
}
return out;
}
對上面說明main裡面使用了Feature_Triangulate_3D_rebuild3.cpp檔案中的TestTriangulation函式,TestTriangulation函式一個引數const vector<CloudPoint>& pcloud是自己定義的類,放在common.h裡面,TestTriangulation函式裡面呼叫了一個函式CloudPointsToPoints(const std::vector<CloudPoint> cpts),這個函式放在common.cpp檔案中
編譯說明:
從main開始,遇到#include"Feature_Triangulate_3D_rebuild3.h“時進入include"Feature_Triangulate_3D_rebuild3.h中,又遇到#include"common.h",把common.h裡面的CloudPoint類申明瞭,把CloudPointsToPoints函式也申明瞭(申明的時候就是告訴到common.cpp裡面去找這個CloudPointsToPoints這個函式),common.h裡面編譯完,回到nclude"Feature_Triangulate_3D_rebuild3.h中,執行#include"common.h"後面的bool TestTriangulation(const vector<CloudPoint>& pcloud, const Matx34d& P, vector<uchar>& status)函式申明,這個函式會遇到 有引數CloudPoint類和CloudPointsToPoints函式,這兩個都在前面申明瞭,所以編譯不會出現問題。所以mian函式裡面的#include"Feature_Triangulate_3D_rebuild3.h"執行完畢,就把我們使用TestTriangulation函式要用到的東西全都搞定了。所有的cpp檔案都通過h標頭檔案呼叫編譯成功。
相關推薦
第六十五篇:VS工程檔案中cpp、h檔案在main中呼叫關係及如何避免出現“找到一個或多個多重定義的符號”
作者:liaojiacai 郵箱: [email protected] 1、出現的問題:”error LNK1169: 找到一個或多個多重定義的符號“的錯誤 2、該問題出現的場景:(假設有一個A.h,A.cpp,main,在main中呼叫了A.cpp
第四十五篇:ReactiveCocoaObjC使用
引導:首先如果要使用 ReactiveCocoaObjC 第三方框架就先需要匯入該框架,我匯入時使用了 cocoapods 匯入的,在 podfile 檔案中輸入以下的內空: use_frameworks! target 'ReactiveCocoaDo
第六十一篇:移植不帶系統應用程式到有ARM-LINUX系統的S32V234上
上一篇講了一下有統的應用程式移植,相對來說比較簡單 從今天開始要移植一個沒有系統的應用程式到S32V234上,處理預處理需要用到ISP外,還要使用APEX,還要使用linux系統管理載入檔案,原來的應用程式中的檔案載入管理是自定義的檔案開啟和讀取函式 先分析一下需要做的工作
fatal error LNK1169:找到一個或多個重定義的符號
ava 文件中 程序 bsp 由於 nbsp .cn 引用 error 這個算是個比較基礎的問題,由於我不是C程序員,本行java,臨時拉來做的,所以有些坑還得自己走出來。 這個問題是由於,全局變量在a.h中定義,在兩個源文件a.cpp和b.cpp中引用,之後被編譯器
第十五篇:JavaScript 之 Dom操作
頁面 對象模型 面向 方法 bsp log gpo eva div 一、後臺管理頁面布局 二、JavaScript函數 三、eval以及時間操作 四、JavaScript作用域 五、JavaScript面向對象模型 六、DOM選擇器 七、DOM事件操作 八、DOM綁定事件的
轉載:SpringBoot非官方教程 | 第十五篇:Springboot整合RabbitMQ
這篇文章帶你瞭解怎麼整合RabbitMQ伺服器,並且通過它怎麼去傳送和接收訊息。我將構建一個springboot工程,通過RabbitTemplate去通過MessageListenerAdapter去訂閱一個POJO型別的訊息。 準備工作 15min ID
SpringBoot非官方教程 | 第十五篇:Springboot整合RabbitMQ
這篇文章帶你瞭解怎麼整合RabbitMQ伺服器,並且通過它怎麼去傳送和接收訊息。我將構建一個springboot工程,通過RabbitTemplate去通過MessageListenerAdapter去訂閱一個POJO型別的訊息。 準備工作 15min ID
第十五篇:前輩opencv學習入門經驗
首先,搞影象處理,熟悉影象演算法是必經之路,如果上過影象處理這門課的話,再好不過。如果沒有,我推薦中科院研究生院劉定生老師的數字影象處理與分析(視訊),這位老師上課引人入勝,值得推薦。其次,在這個階段,配套的書籍自然是《岡薩雷斯版數字影象處理》這本書,最好同時用matlab軟體,模擬每一個影象演算法案例,推薦
一起來學SpringBoot | 第十五篇:actuator與spring-boot-admin 可以說的祕密
SpringBoot 是為了簡化 Spring 應用的建立、執行、除錯、部署等一系列問題而誕生的產物,自動裝配的特性讓我們可以更好的關注業務本身而不是外部的XML配置,我們只需遵循規範,引入相關的依賴就可以輕易的搭建出一個 WEB 工程 一起來學Spr
Python 學習 第十五篇:模塊搜索路徑和包導入
部分 blank 所有 python 環境變量 bsp 引入 html pytho 在導入自定義的模塊時,除了指定模塊名之外,也需要指定目錄,由於Python把目錄稱作包,因此,這類導入被稱為包導入。包導入把計算機上的目錄變成Python的命名空間,而目錄中所包含的子目錄和
SpringBoot第十五篇:swagger構建優雅文件
作者:追夢1819 原文:https://www.cnblogs.com/yanfei1819/p/11007470.html 版權宣告:本文為博主原創文章,轉載請附上博文連結! 引言 前面的十四篇文介紹了 SpringBoot 的一些基本和常用的功能。後面,我們將介紹 SpringBoot 的高階的功
跟我學SpringCloud | 第十五篇:微服務利劍之APM平臺(一)Skywalking
目錄 SpringCloud系列教程 | 第十五篇:微服務利劍之APM平臺(一)Skywalking 1. Skywalking概述 2. Skywalking主要功能 3. Skywalking主要特性
PowerBI開發 第十五篇:Power BI的行級安全
Power BI支援行級安全(Row-Level Security,RLS)的許可權控制,用於限制使用者對Dashboard、報表和DataSet的訪問。使用者瀏覽的報表是相同的,但是看到的資料卻是不同的。 RLS內部通過DAX函式 username() 和 userprincipalname()來實現,R
mysql 第三十五篇文章~xtarbackup增量備份以及策略
判斷 config 服務器 dir 難度 修改 初始 一周 -a 一 簡介: 今天咱們來探討下增量備份的策略 二 背景: 隨著數據量的日益增長,全備已經不現實了,所以探討並測試了增量備份策略 三 具體策略: 1 一周為界限,一天做全備,其他時間以全備為基礎進行增量備份
mysql 第四十五篇文章~初探MGR
ini 擁有 bsp gtid_mode stat 執行 配置文件 不同 插入數據 一 簡介 :MGR一直沒有時間測試,今天咱們來初步了解搭建一下唄 二 環境: mysql5.7.20 單臺機器 啟動三實例 三 mysql 搭建: 1 建立相關目錄+
第四十五篇 入門機器學習——數據加載和簡單的數據探索
com 矩陣 desc ica 花瓣 入門機器學習 data 類別 機器學習 No.1. 導入相關類庫,並加載鳶尾花數據集 No.2. 這個鳶尾花數據集類似於一個字典,可以查看都有哪些鍵 No.3. ‘DESCR‘這個鍵對應的值為鳶尾花數據集的文檔,簡單
Android Studio 第六十五期 - Android業務組件庫
base png 拍照 builder 購物車 lse utils 文檔 user 目前市面上常用的效果集合,持續更新: 地址:https://github.com/geeklx/APPkuangjia/tree/master/baselibrary/src/
python學習第六十八天:數據庫相關操作
order 運行 反向 all djang 建表 ima nag publish ORM簡介 orm能幹的事: 1 創建表,修改表,刪除表 2 插入數據 3 修改數據 4 刪除數據 不能幹:不能創建數據庫 類名-----》表 對象------》一條數據 屬性
python學習第七十五天:多表查詢
object rim pytho 連表查詢 mit str () tle detail 創建模型 class Book(models.Model): nid = models.AutoField(primary_key=True) name = models
python學習第八十五天:網絡爬蟲之數據解析方式
數據解析 模式 end 解析 多次 pre 綜合練習 直接 list Python網絡爬蟲之數據解析方式 正則解析 單字符: . : 除換行以外所有字符 [] :[aoe] [a-w] 匹配集合中任意一個字符 \d :數字