如何在命名空间中声明外部全局然后定义它?

时间:2017-07-15 05:18:20

标签: c++ namespaces extern

似乎每个Arduino库都使用Arduino Serial库来打印调试消息。我目前正在尝试将此库集成到我的项目https://github.com/jrowberg/i2cdevlib/tree/master/Arduino/I2Cdev中。我正在使用我自己的python程序从我的atmega 2560接收消息。我想尝试一些库而不更改他们的源代码但是因为串行库我必须将他们的Serial.print()调用转换为我自己的API调用。因为我不得不为每个库弄乱,所以我决定为Serial库创建一个包装器,其中我有一个名为Serial的全局变量。那个Serial变量将是我的Serial包装器定义为extern。

我在SerialWrapper命名空间中有serial。我希望将全局变量Serial定义为extern,也在serial命名空间中。

// SerialWrapper.h
namespace serial {

    enum SerialType {
        HEX,
        DEC
    };

    class SerialWrapper {
    public:
        SerialWrapper(ground::Ground& ground);
        void print(const char *string);
        void print(uint8_t data, SerialType type);
    private:
        ground::Ground& ground_;
    };

    extern SerialWrapper Serial;
}

然后在源文件中我定义了方法和全局变量,如此

// SerialWrapper.cpp
#include "SerialWrapper.h"

serial::SerialWrapper Serial = serial::SerialWrapper(ground::Ground::reference());

serial::SerialWrapper::SerialWrapper(ground::Ground& ground) : ground_( ground )
{

}

void serial::SerialWrapper::print(const char *string)
{
    ground_.sendString(string);
}

void serial::SerialWrapper::print(uint8_t data, serial::SerialType type)
{

}

尝试测试库,我在我的主要方法中调用它

// main.cpp
using namespace serial;

int main( void )
{
    Serial.print("Hello World!");
}

为了使这些库与我的SerialWrapper兼容,我需要它以这种方式工作。但是,当我编译时,我从main.cpp得到错误,即undefined reference to 'serial::Serial'

您可以在此处查看mpu分支下的所有源代码(很快将合并为主版)https://github.com/jkleve/quaddrone

1 个答案:

答案 0 :(得分:-1)

要使未定义的引用消失,我必须将声明移到命名空间之外,如此

// SerialWrapper.h
namespace serial {

    enum SerialType {
        HEX,
        DEC
    };

    class SerialWrapper {
    public:
        SerialWrapper(ground::Ground& ground);
        void print(const char *string);
        void print(uint8_t data, SerialType type);
    private:
        ground::Ground& ground_;
    };
}

extern serial::SerialWrapper Serial;

我不知道为什么要这样做。也许其他人可以在命名空间中声明extern的问题上发表评论。

我还发现了这个引用https://www.ics.com/designpatterns/book/namespace-example.html

按照参考文献中的方法,您还可以设置声明和定义,如下所示

// SerialWrapper.h
namespace serial {

    enum SerialType {
        HEX,
        DEC
    };

    class SerialWrapper {
    public:
        SerialWrapper(ground::Ground& ground);
        void print(const char *string);
        void print(uint8_t data, SerialType type);
    private:
        ground::Ground& ground_;
    };
    extern SerialWrapper Serial;
}

必须将定义更改为此。

// SerialWrapper.cpp
#include "SerialWrapper.h"

serial::SerialWrapper serial::Serial = serial::SerialWrapper(ground::Ground::reference());