C++ 多个定义,即使只给出一个定义

Posted

技术标签:

【中文标题】C++ 多个定义,即使只给出一个定义【英文标题】:C++ Multiple definitions even though only one definition is given 【发布时间】:2017-04-09 07:50:36 【问题描述】:

我正在尝试制作一个小的无序映射,我可以用它来永久存储键和值,作为一种字典。 TengwarChar 类型只是一个有两个值的对象,一个字符串和一个枚举,稍后我也会添加方法。我使用的标头如下:

#ifndef TENGWARLIBRARY_H
#define TENGWARLIBRARY_H

#include "tengwarchar.h"
#include <unordered_map>
#include <algorithm>
#include <string>

typedef std::unordered_map<std::string, TengwarChar> CharMap;

extern const CharMap numbers = 
    "0", TengwarChar("ð", SHORT),
    "1", TengwarChar("ñ", SHORT),
    "2", TengwarChar("ò", SHORT),
    "3", TengwarChar("ó", SHORT),
    "4", TengwarChar("ô", SHORT),
    "5", TengwarChar("õ", SHORT),
    "6", TengwarChar("ö", SHORT),
    "7", TengwarChar("÷", SHORT),
    "8", TengwarChar("ø", SHORT),
    "9", TengwarChar("ù", SHORT)
 ;

std::string translateFromEnglishToTengwar(std::string str);
std::string translateFromTengwarToEnglish(std::string str);

#endif // TENGWARLIBRARY_H

然后,我有一个简单的测试 cpp 文件随之而来:

#include "tengwarlibrary.h"

std::string translateFromEnglishToTengwar(std::string str)

    std::transform(str.begin(), str.end(), str.begin(), (int (*)(int))std::tolower);
    return str;


std::string translateFromTengwarToEnglish(std::string str)

    return "Hello world.";

问题是,在我的主函数中调用translateFromTengwarToEnglish 时,我不断收到“数字的多重定义[abi:cxx11]”错误,尽管我相当确定我只在标题中定义了一次文件,也使用标题保护。如果它可能有帮助,这是我不起眼的主要 cpp 文件:

#include "mainwindow.h"
#include <QApplication>

#include <iostream>

#include "utils/tengwarlibrary.h"

int main(int argc, char *argv[])


    std::string s = "BlaH FElfeFEJI, IEORlfj";
    std::cout<<translateFromEnglishToTengwar(s)<<std::endl;

    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();

【问题讨论】:

您只能在头文件中声明带有外部链接的符号。它们的定义需要在使用它们的翻译单元中。 @HenriMenke 当我删除 extern const 位并假设它是一个全局变量时,我得到了同样的错误。当我可以在标头中使用初始化程序时,我真的不想将定义放入源文件中。 @AndrewLalis 你不能。按照您编写的方式,每个源文件都隐含地获取了 numbers 数组的 定义。您应该在标头中声明该数组,并在一个源文件中定义它(不带 extern 关键字)。 @HellmarBecker 那么我是否应该在我的一个源中创建一个“init”函数来定义我需要的所有数组? 【参考方案1】:

根据C++ standard§3.1.2

声明是一个定义,除非它声明一个函数而不指定函数的主体,它包含 extern 说明符或链接说明,并且既不包含 初始化器也不是函数体...

头文件tengwarlibrary.hnumbers的声明是带有初始化器的外部声明。所以它也是一个定义。

由于您在两个源文件中包含了tengwarlibrary.h(其中一个定义了translateFromTengwarToEnglish(),一个定义了main()),它们都具有numbers 的定义。因此,错误。

为了解决这个问题,在头文件中声明 numberextern 并在单个源文件中初始化它。

【讨论】:

以上是关于C++ 多个定义,即使只给出一个定义的主要内容,如果未能解决你的问题,请参考以下文章

c++ - 是不是必须定义所有静态类方法,即使不使用?

C++:当我定义运算符时,所有成员函数都会给出隐式定义错误

即使使用 `-dec-math`,gfortran 也会对 `dacosd_` 给出未定义的引用

急!请高手指教c++如何定义一个参数个数不确定的函数?

是啥导致 c++ std::string 变量在传递给类时给出冲突的定义

C++面向对象之封装篇(上)