CodeBlocks 编译器在我的头文件中声明的函数的使用中给出“未定义的引用”错误

CodeBlocks Compiler Giving "Undefined Reference" Error Over Usage of a Function Declared in My Header File

提问人:Frasher Gray 提问时间:9/12/2023 最后编辑:Vlad from MoscowFrasher Gray 更新时间:9/12/2023 访问量:170

问:

尝试构建和运行我的 C++ 项目时出现以下错误:

||=== Build: Debug in CS II (compiler: GNU GCC Compiler) ===|

obj\Debug\main.o||In function 'main':|
|30|undefined reference to '(anonymous namespace)::deleteRepeats(char*)'||

|error: ld returned 1 exit status|
||=== Build failed: 2 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|

我的每个文件的代码如下(如果很多错误或完全错误,我不会感到惊讶,因为我根本无法对其进行测试,我的重点是解决这个问题):

主 .cpp:

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

int main()
{
    char originalArray[SIZE];
    originalArray[0] = 'a';
    originalArray[1] = 'b';
    originalArray[2] = 'b';
    originalArray[3] = 'c';
    originalArray[4] = 'a';
    originalArray[5] = 'c';
    originalArray[6] = 'a';
    originalArray[7] = 'c';
    originalArray[8] = 'b';
    originalArray[9] = 'c';
    char *noRepeats;
    noRepeats = deleteRepeats(&(originalArray[0]));
    std::cout << noRepeats;
    return 0;

}

实现.hpp:

#ifndef IMPLEMENTATION_HPP
#define IMPLEMENTATION_HPP
namespace
{
    const int SIZE = 10;
    char* deleteRepeats(char*);
}
#endif

实现:.cpp:

#include "implementation.hpp"

char* deleteRepeats(char* array_to_edit)
{
    char new_array[SIZE];
    int num_of_unique_letters_seen = 0;
    for (int letter = 0; letter < SIZE; letter++)
    {
        bool already_exists = false;
        for (int letter_seen = 0; letter_seen < num_of_unique_letters_seen; letter_seen++)
        {
            if (array_to_edit[letter] == new_array[letter_seen])
            {
                already_exists = true;
            }
        }
        if (!already_exists)
        {
            new_array[num_of_unique_letters_seen] = array_to_edit[letter];
            num_of_unique_letters_seen++;
        }
    }
    return &new_array[0];
}

在这个问题的答案的评论中,我被提示问这个问题,这非常相似,但是当问题出现时,我的项目中已经完成了公认的答案。

命名空间被赋予名称的代码:

主 .cpp:

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

int main()
{
    char originalArray[dts::SIZE];
    originalArray[0] = 'a';
    originalArray[1] = 'b';
    originalArray[2] = 'b';
    originalArray[3] = 'c';
    originalArray[4] = 'a';
    originalArray[5] = 'c';
    originalArray[6] = 'a';
    originalArray[7] = 'c';
    originalArray[8] = 'b';
    originalArray[9] = 'c';
    char *noRepeats;
    noRepeats = dts::deleteRepeats(&(originalArray[0]));
    std::cout << noRepeats;
    return 0;

}

实现:.cpp:

#include "implementation.hpp"

char* deleteRepeats(char* array_to_edit)
{
    char new_array[dts::SIZE];
    int num_of_unique_letters_seen = 0;
    for (int letter = 0; letter < dts::SIZE; letter++)
    {
        bool already_exists = false;
        for (int letter_seen = 0; letter_seen < num_of_unique_letters_seen; letter_seen++)
        {
            if (array_to_edit[letter] == new_array[letter_seen])
            {
                already_exists = true;
            }
        }
        if (!already_exists)
        {
            new_array[num_of_unique_letters_seen] = array_to_edit[letter];
            num_of_unique_letters_seen++;
        }
    }
    for (int letter = 0; letter < dts::SIZE; letter++)
    {
        array_to_edit[letter] = new_array[letter];
    }
    return array_to_edit;
}

实现.hpp:

#ifndef IMPLEMENTATION_HPP
#define IMPLEMENTATION_HPP
namespace dts
{
    const int SIZE = 10;
    char* deleteRepeats(char*);
}
#endif
C++ 命名空间 头文件 函数定义

评论

3赞 Evg 9/12/2023
你为什么使用?namespace
6赞 Evg 9/12/2023
但匿名命名空间隐藏了名称。
1赞 Ted Lyngmo 9/12/2023
不,请显示代码,而不是屏幕截图。
1赞 PaulMcKenzie 9/12/2023
@FrasherGray 你的问题看起来和这个一样。你们俩都上同一门课程吗?
3赞 infinitezero 9/12/2023
您需要在 .cpp 文件中的函数周围放置相同的命名空间

答:

0赞 Vlad from Moscow 9/12/2023 #1

在未命名命名空间中声明的函数具有内部链接。因此,您需要在每个编译单元中定义它。

否则,请在命名命名空间中声明它。

来自 C++17 标准(6.5 程序和链接)

4 未命名的命名空间或在未命名的命名空间中直接或间接声明的命名空间具有内部链接。所有其他命名空间都有外部链接。具有命名空间范围的名称,如果上面没有给出内部链接,则该名称与封闭的命名空间具有相同的链接,如果它是

//... (4.2) — 函数;或

另请注意,您将函数定义放在全局命名空间中,但在封闭的未命名命名空间中声明。

还有一句话。第一个函数定义是 invald。

char* deleteRepeats(char* array_to_edit)
{
    char new_array[SIZE];

    //...
    return &new_array[0];
}

您将返回指向本地数组的指针,该数组在退出函数后将不处于活动状态。取消引用此类指针将调用未定义的行为。

Alsp 这句话

std::cout << noRepeats;

还调用未定义的行为,因为数组不包含字符串。

你使用辅助阵列的方法无效,甚至是错误的。This for 循环

for (int letter = 0; letter < dts::SIZE; letter++)
{
    array_to_edit[letter] = new_array[letter];
}

由于循环的条件,不仅用唯一的字母填充数组。array_to_editletter < dts::SIZE

该函数应处理字符串。

1赞 infinitezero 9/12/2023 #2

命名空间的思想是解决冲突,例如,如果函数碰巧具有相同的名称。有点像人们的姓氏,将约翰·贝克森和约翰·米勒区分开来。

因此,一个 John 位于命名空间 Bakerson 中,另一个位于命名空间 Miller 中。

如果使用命名空间,请始终告诉编译器您的函数属于哪个命名空间。

.hpp 文件

namespace Bakerson {
  void John();
}

namespace Miller {
  void John();
}

.cpp

namespace Bakerson {
  void John(){
    std::cout << "I'm John Bakerson.\n";
  }
}

namespace Miller {
  void John(){
    std::cout << "I'm John Miller.\n";
  }
}