sun_chuan 发表于 2024-7-21 17:06:42

类模板编译报错

这段代码为啥报错?#include <iostream>

template <class T,int len>
class Array
{
private:

    T items;
public:
    Array()
    {
      memset(items, 0, sizeof(items));
    }
    ~Array();

    T& operator[](int i)
    {
      return items;
    }
    const T& operator[](int i)const
    {
      return items;
    }
};


int main()
{
    Array<std::string, 10> a;
    a = "哈哈";
}

1>------ 已启动生成: 项目: 模板示例:数组, 配置: Debug x64 ------
1>模板示例:数组.cpp
1>模板示例:数组.obj : error LNK2019: 无法解析的外部符号 "public: __cdecl Array<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,10>::~Array<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,10>(void)" (??1?$Array@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@$09@@QEAA@XZ),函数 main 中引用了该符号
1>C:\Users\Administrator\source\repos\模板示例:数组\模板示例:数组\x64\Debug\模板示例:数组.exe : fatal error LNK1120: 1 个无法解析的外部命令
1>已完成生成项目“模板示例:数组.vcxproj”的操作 - 失败。
========== 生成: 0 成功,1 失败,0 最新,0 已跳过 ==========
========== 生成 于 17:05 完成,耗时 03.543 秒 ==========

FishC 发表于 2024-7-21 17:06:53

哎呀,这段代码里的问题就像是一个不合时宜的笑话,让我们来解开它的谜团!

首先,您定义了一个模板类 `Array`,这很好,但在这个类中,您并没有为 `T` 声明出类型,也就是说编译器不知道 `T` 是什么。您需要在类声明的地方加上 `typename` 或者 `class` 关键字来告诉编译器 `T` 是一个类型。

更重要的是,您定义了一个析构函数 `~Array()`,但是没有提供它的实现。这就像一个厨师写了菜单但从来不做饭,每当有人点餐时,就会很尴尬。解决这个问题的一种方法是简单删除 `~Array();` 声明,因为如果没有特殊的资源管理需求,编译器可以自动生成一个默认的析构函数。

还有一点:您的 `operator` 重载函数应该使用 `operator[]` 而不是 `operator(int i)`,因为这是常用的数组下标操作符。这样用户在使用这个类的时候才不会觉得自己在拼写错误。

最后,您在 `main` 函数中创建了一个 `Array` 对象,而没有指定 `T` 的类型。这会导致编译器无法判断 `Array a;` 的类型。

让我们修正这些错误后的代码如下:

#include <iostream>
#include <cstring>
#include <string>

template <typename T>
class Array
{
private:
    T items;// 假设数组大小为100
public:
    Array()
    {
      memset(items, 0, sizeof(items));
    }
   
    ~Array() = default;// 使用默认析构函数

    T& operator[](int i)// 修正为 operator[]
    {
      return items;// 使用下标访问数组元素
    }

    const T& operator[](int i) const
    {
      return items;
    }
};

int main()
{
    Array<std::string> a; // 指定T为std::string
    a = "哈哈";// 使用下标赋值
    std::cout << a << std::endl;// 输出 "哈哈"
    return 0;
}

现在代码应该能顺利编译并运行!通过这些小改变,您的代码就像十足的幽默段子一样,变得清晰而有条理!希望能帮到您!如果还有其他问题,尽管问我!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

sun_chuan 发表于 2024-7-21 17:12:22

我按照你的要求改正了代码,但是为啥打印是乱码?@<綀
C:\Users\Administrator\source\repos\模板示例:数组\模板示例:数组\x64\Debug\模板示例:数组.exe (进程 10728)已退出,代码 为 0。
按任意键关闭此窗口. . .

FishC 发表于 2024-7-21 17:12:30

sun_chuan 发表于 2024-07-21 17:12
我按照你的要求改正了代码,但是为啥打印是乱码?@

哦,打印出乱码就像是在茶馆里听见了一段古老的京剧,完全听不懂!码农朋友,这里有几个可能导致乱码的原因,让我们来一一排查。

1. **字符数组与字符串**:您在构建 `Array` 类的时候定义了一个 `T items;`,但是如果 `T` 是 `std::string` 或者其他类型且没有具体大小的话,直接用 `memset` 初始化可能会导致问题。`memset` 是用于设置内存的原始字节操作,不适合复杂数据类型(如 `std::string`)。对于字符串,请不要使用 `memset`,而是应该用构造函数去初始化。

2. **数组大小问题**:如果 `items` 是个动态数组或类似于这样的数据结构,你需要决定它的大小。举个例子,可以使用 `std::vector<T>` 来容纳任意数量的元素,它会自动管理内存。

3. **输出方式**:请确保您打印字符串的方式是正确的,尤其是关于编码。如果是 `char` 数组,用 `printf` 或者直接输出,而如果是 `std::string`,用 `cout`。

4. **修改后的代码示例**:

#include <iostream>
#include <string>
#include <vector>

template <typename T>
class Array {
private:
    std::vector<T> items;// 使用 vector 来存储数组
public:
    Array(int size) : items(size) { // 构造函数接受数组大小
      for (auto& item : items) {
            item = T(); // 初始化
      }
    }

    ~Array() = default;

    T& operator[](int i) {// 正确重载下标操作符
      return items.at(i); // 使用 at() 以防止越界
    }

    const T& operator[](int i) const {
      return items.at(i);
    }
};

int main() {
    Array<std::string> a(10); // 创建一个容量为10的字符串数组
    a = "哈哈";// 使用下标赋值
    std::cout << a << std::endl; // 打印第一个元素
}

在这个例子中,我使用 `std::vector` 管理动态大小的数组,并且通过下标访问字符串。这种情况下使用 `std::vector` 会更安全,也不会出现乱码问题。

试试看这个版本的代码!希望这次打印出来的是清晰可读的中文,而不是古怪的乱码!如果还有问题,就像你进了一个迷宫一样,继续向我询问,我们一起找到出口!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页: [1]
查看完整版本: 类模板编译报错