c++ - 如何解决对自己类的构造函数和析构函数的 undefined reference 的问题?

标签 c++ linux

我编写了一个简单的程序,它使用带有构造函数、析构函数和数据成员的类。当我尝试初始化一个对象时,调试器告诉我没有析构函数和析构函数。我在Clion、VS2019和VSCode中尝试过。我得到了与 4) 相同的结果。我不知道当我实际创建构造函数和析构函数时它总是发生。

请帮助我。谢谢!

1) String.h

#ifndef TEST_STRING_H
#define TEST_STRING_H

class String {
  public:
    explicit String(const char *cstr = nullptr);

    String(const String &str);

    String &operator=(const String &str);

    ~String();

    char *get_c_str() const { return m_data; }

  private:
    char *m_data;
};

#endif // TEST_STRING_H

2) String.cpp

#include "String.h"
#include <cstring>

inline String::String(const char *cstr) {
    if (cstr) {
        m_data = new char[strlen(cstr) + 1];
        strcpy(m_data, cstr);
    } else {
        m_data = new char[1];
        *m_data = '\0';
    }
}

inline String::~String() { delete[] m_data; }

inline String &String::operator=(const String &str) {
    if (this == &str)
        return *this;

    delete[] m_data;
    m_data = new char[strlen(str.m_data) + 1];
    strcpy(m_data, str.m_data);
    return *this;
}

inline String::String(const String &str) {
    m_data = new char[strlen(str.m_data) + 1];
    strcpy(m_data, str.m_data);
}

3) main.cpp

#include <iostream>
#include "String.h"

using namespace std;

int main() {
    String s1("hello");
    return 0;
}

4)结果

/tmp/ccCIK0hs.o: In function `main':
/home/Projects/test/main.cpp:7: undefined reference to `String::String(char const*)'
/home/Projects/test/main.cpp:7: undefined reference to `String::~String()'
collect2: error: ld returned 1 exit status

最佳答案

您使用inline说明符的方式存在“问题”。修复方法只是从所有 String 方法定义中删除 inline 说明符,以使错误消失。

让我们深入研究一下为什么你的程序格式错误。

我将使用 cppreference inline specifier 中的积分:

An inline function or inline variable (since C++17) has the following properties:

  1. The definition of an inline function or variable (since C++17) must be reachable in the translation unit where it is accessed (not necessarily before the point of access).
  2. An inline function or variable (since C++17) with external linkage (e.g. not declared static) has the following additional properties:
    1. There may be more than one definition of an inline function or variable (since C++17) in the program as long as each definition appears in a different translation unit and (for non-static inline functions and variables (since C++17)) all definitions are identical. For example, an inline function or an inline variable (since C++17) may be defined in a header file that is #include'd in multiple source files.
    2. It must be declared inline in every translation unit.
    3. It has the same address in every translation unit.

Ad 1) 简而言之:如果您有一个内联函数定义,如 inline String::String(const char *cstr) { some },您可以从同一个 .cpp 文件调用它。如果您从其他 .cpp 文件调用它,就像您在 String.cpp 中定义函数但从 main.cpp 调用它一样,这是无效的。

广告 2) 您的函数不是静态的,因此本节适用。

Ad 2.1) 如果您的 String.cpp 中有 inline String::String(const char *cstr),则 String.h 的类声明中必须有 inline String::String(const char *cstr);。如果您使用 inline 声明它,则它在任何地方都必须是 inline,在 String.h 中也是如此。现在在您的代码中,String.h 中没有内联

解决方法是遵守 12.1 中的规则。因此,要么从 String.cpp 中删除 inline 关键字,然后让所有函数只是具有外部链接的普通函数,这是正常的编程方式。

或者,如果您必须让函数具有 inline 功能,请将所有代码从 String.cpp 移动到 String.h 并将 inline 添加到这些成员函数声明中。就像下面的代码:

#ifndef TEST_STRING_H
#define TEST_STRING_H

class String {
  public:
    inline explicit String(const char *cstr = nullptr);
    inline String(const String &str);
    inline String &operator=(const String &str);
    inline ~String();
    inline char *get_c_str() const { return m_data; }
  private:
    char *m_data;
};

#include <cstring>

inline String::String(const char *cstr) {
    if (cstr) {
        m_data = new char[strlen(cstr) + 1];
        strcpy(m_data, cstr);
    } else {
        m_data = new char[1];
        *m_data = '\0';
    }
}

inline String::~String() { delete[] m_data; }

inline String &String::operator=(const String &str) {
    if (this == &str)
        return *this;

    delete[] m_data;
    m_data = new char[strlen(str.m_data) + 1];
    strcpy(m_data, str.m_data);
    return *this;
}

inline String::String(const String &str) {
    m_data = new char[strlen(str.m_data) + 1];
    strcpy(m_data, str.m_data);
}

#endif // TEST_STRING_H

请注意,“在类定义内部”定义的函数是隐式内联的,因此您也可以将函数定义移动到类定义内部。

关于c++ - 如何解决对自己类的构造函数和析构函数的 undefined reference 的问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59930828/

相关文章:

c++ - Arduino 字符串比较不起作用

python - 将程序作为可执行文件运行时设置默认 python 版本 ./xxx.py - 在 linux 上

linux - 使用awk从两个文件写一个两列文件

php - 如何将 ioncube(或其他扩展)集成到 phpbrew php 版本中?

java - 我如何从 snapcraft 在 ubuntu 中安装和设置 open jdk

Ruby IO 无法按预期在 Windows 上工作,随机卡在 put 和 read 上

c++ - 为什么指针返回值而不是地址?

c++ - GMP库函数

C++ 字符编码

c++ - C++/CLI 中的十进制到十六进制函数