2017-08-14 68 views
1

我有三個文件:包括問題:「多重定義」,「先在這裏定義的」

main.cpp 
MyClass.cpp 
MyClass.hpp 

我有一個庫的頭文件,"testLib.hpp",我想在MyClass.hpp包括這樣我可以有一個testLib的對象是類屬性。

我在MyClass.cppmain.cpp中包括MyClass.hpp。當嘗試編譯項目,我收到以下錯誤

MyClass.cpp multiple definition of 'testLib::testLib::function1() 
obj/Release/main.o:main.cpp first defined here 
MyClass.cpp multiple definition of 'testLib::testLib::function2() 
obj/Release/main.o:main.cpp first defined here 

等。

main.cppMyClass.cpp都包括MyClass.hpp(其包括testLib.hpp)。從錯誤判斷,看起來MyClass.cpp正試圖在庫函數已包含在main.cpp之後。不過,我已經包括了目前在0​​的警衛,所以我不明白它是如何試圖包括MyClass.hpp兩次。

下面的代碼:

MyClass.hpp

#ifndef THIS_HEADER_H 
#define THIS_HEADER_H 

#include <stdint.h> 
#include <iostream> 
#include "testLib/testLib.hpp" 

class MyClass 
{ 

public: 
    void test(); 
    int foo; 

private: 
    uint32_t bar; 
    //I want to include an object from the library as part of this class 
    //TestLib::Device device; 
}; 

#endif 

MyClass.cpp

#include <stdio.h> 
#include "MyClass.hpp" 

void MyClass::test() 
{ 

} 

的main.cpp

#include <iostream> 
#include "MyClass.hpp" 

using namespace std; 

int main() 
{ 
    cout << "Hello world!" << endl; 
    return 0; 
} 

任何幫助將不勝感激!

編輯 我試圖隱藏實際的文件名,使問題更普遍的和明確的,但似乎問題可能來自「testLib.hpp」,這是我沒有寫來產生。該文件實際上是以下「sweep.hpp」文件。我得到了「的多個定義/在這裏先定義」的錯誤爲每個在此文件中的公共職能:

sweep.hpp

#ifndef SWEEP_DC649F4E94D3_HPP 
#define SWEEP_DC649F4E94D3_HPP 

/* 
* C++ Wrapper around the low-level primitives. 
* Automatically handles resource management. 
* 
* sweep::sweep - device to interact with 
* sweep::scan - a full scan returned by the device 
* sweep::sample - a single sample in a full scan 
* 
* On error sweep::device_error gets thrown. 
*/ 

#include <cstdint> 
#include <memory> 
#include <stdexcept> 
#include <vector> 

#include <sweep/sweep.h> 

namespace sweep { 

// Error reporting 

struct device_error final : std::runtime_error { 
    using base = std::runtime_error; 
    using base::base; 
}; 

// Interface 

struct sample { 
    const std::int32_t angle; 
    const std::int32_t distance; 
    const std::int32_t signal_strength; 
}; 

struct scan { 
    std::vector<sample> samples; 
}; 

class sweep { 
public: 
    sweep(const char* port); 
    sweep(const char* port, std::int32_t bitrate); 
    void start_scanning(); 
    void stop_scanning(); 
    bool get_motor_ready(); 
    std::int32_t get_motor_speed(); 
    void set_motor_speed(std::int32_t speed); 
    std::int32_t get_sample_rate(); 
    void set_sample_rate(std::int32_t speed); 
    scan get_scan(); 
    void reset(); 

private: 
    std::unique_ptr<::sweep_device, decltype(&::sweep_device_destruct)> device; 
}; 

// Implementation 

namespace detail { 
struct error_to_exception { 
    operator ::sweep_error_s*() { return &error; } 

    ~error_to_exception() noexcept(false) { 
    if (error) { 
     device_error e{::sweep_error_message(error)}; 
     ::sweep_error_destruct(error); 
     throw e; 
    } 
    } 

    ::sweep_error_s error = nullptr; 
}; 
} 

sweep::sweep(const char* port) 
    : device{::sweep_device_construct_simple(port, detail::error_to_exception{}), &::sweep_device_destruct} {} 

sweep::sweep(const char* port, std::int32_t bitrate) 
    : device{::sweep_device_construct(port, bitrate, detail::error_to_exception{}), &::sweep_device_destruct} {} 

void sweep::start_scanning() { ::sweep_device_start_scanning(device.get(), detail::error_to_exception{}); } 

void sweep::stop_scanning() { ::sweep_device_stop_scanning(device.get(), detail::error_to_exception{}); } 

bool sweep::get_motor_ready() { return ::sweep_device_get_motor_ready(device.get(), detail::error_to_exception{}); } 

std::int32_t sweep::get_motor_speed() { return ::sweep_device_get_motor_speed(device.get(), detail::error_to_exception{}); } 

void sweep::set_motor_speed(std::int32_t speed) { 
    ::sweep_device_set_motor_speed(device.get(), speed, detail::error_to_exception{}); 
} 

std::int32_t sweep::get_sample_rate() { return ::sweep_device_get_sample_rate(device.get(), detail::error_to_exception{}); } 

void sweep::set_sample_rate(std::int32_t rate) { 
    ::sweep_device_set_sample_rate(device.get(), rate, detail::error_to_exception{}); 
} 

scan sweep::get_scan() { 
    using scan_owner = std::unique_ptr<::sweep_scan, decltype(&::sweep_scan_destruct)>; 

    scan_owner releasing_scan{::sweep_device_get_scan(device.get(), detail::error_to_exception{}), &::sweep_scan_destruct}; 

    auto num_samples = ::sweep_scan_get_number_of_samples(releasing_scan.get()); 

    scan result; 
    result.samples.reserve(num_samples); 

    for (std::int32_t n = 0; n < num_samples; ++n) { 
    auto angle = ::sweep_scan_get_angle(releasing_scan.get(), n); 
    auto distance = ::sweep_scan_get_distance(releasing_scan.get(), n); 
    auto signal = ::sweep_scan_get_signal_strength(releasing_scan.get(), n); 

    result.samples.push_back(sample{angle, distance, signal}); 
    } 

    return result; 
} 

void sweep::reset() { ::sweep_device_reset(device.get(), detail::error_to_exception{}); } 

} // ns 

#endif 
+0

您是否嘗試過#pragma一次 –

+5

包含防護措施會阻止將同一個頭文件包含在同一個源中兩次。它們不會阻止將相同的頭文件包含到多個源文件中(它們也不應該;這正是頭文件的預期用法)。主要的錯誤是'testLib.hpp'頭文件定義了幾個函數。一個頭文件只應該聲明函數(應該在某個源文件中定義);或者用'inline'關鍵字來定義它們。 –

+0

@IgorTandetnik感謝您的回覆。我在原始文章中包含了我命名爲'testLib.hpp'的實際庫文件(sweep.hpp)。我沒有寫sweep.hpp。看起來他們確實聲明瞭一些我得到錯誤的功能。所以你說這個錯誤完全來自sweep.hpp? – user3878723

回答

1

你的問題的一個簡化版本:

馬車。 HPP

int function() { return 0; } 

的main.cpp

#include "buggy.hpp" 
int main() { return 0; } 

other.cpp

#include "buggy.hpp" 

的問題是,buggy.hpp定義function,不只是宣佈。擴展標題包含之後,這意味着在main.cppother.cpp中聲明瞭function - 這是不允許的。

修復方法是聲明functioninline,它允許在多個翻譯單元中聲明函數。

inline int function() { return 0; } 

事實上,允許多個定義是inline到C++ 標準含義。編譯器可以將它視爲暗示函數體可以在線擴展。好的不會;他們更擅長做出那種程序員的決定)。