c++类模板成员函数报错

类模板成员函数要不就在类模板中实现,要不就和类模板写在同一个文件中。

否则然会出现下面错误:

>main.obj : error LNK2019: 无法解析的外部符号 "public: int __thiscall vec<int>::pop_back(void)" (?pop_back@?$vec@H@@QAEHXZ),该符号在函数 _main 中被引用
1>main.obj : error LNK2019: 无法解析的外部符号 "public: void __thiscall vec<int>::push_back(int)" (?push_back@?$vec@H@@QAEXH@Z),该符号在函数 _main 中被引用

示例如下:

main.cpp

#include <iostream>
#include "vec.h"
using namespace std;

int main()
{    
    vec<int> s;
    s.push_back(1);
    s.push_back(2);
    s.push_back(3);
    s.push_back(5);
    s.push_back(6);

    try
    {
        while (1)
            cout<<s.pop_back()<<endl;
    }
    catch (const runtime_error &e)
    {
        cerr<<e.what()<<endl;
    }

    system("pause");
}

vec.h

#pragma once
template<class T>
class vec
{
public:

    vec()
        :vect(new T[capacity]),
        capacity(3),
        size(0){};
    ~vec()
    {
        delete[] vect;
    }

    int capacity;
    int size;
    T *vect;

    void push_back(T t);    
    T pop_back();

};

template<class T>
void vec<T>::push_back(T t)
{
    if(size==capacity)
    {
        capacity=capacity*2;
        T *tmp_vec=new T[capacity];
        for(int i=0;i<size;i++)        //我想这里一个个复制并不理想,做个数据结构,用指针连接也许更好
            tmp_vec[i]=vect[i];        //不过用指针连接,速度上去了,运行空间也变大了
        delete[] vect;
        vect=tmp_vec;
    }
    vect[size]=t;
    size++;
}

template<class T>
T vec<T>::pop_back()
{
    if(size==0)
        throw std::runtime_error("vect is empty");
    else
    {
        size--;
        return vect[size];
    }
}

 

转载于:https://www.cnblogs.com/tiandsp/p/3299729.html

### C++ 转换构造函数报错原因及解决方案 #### 1. 报错的原因分析 转换构造函数是一种特殊的构造函数,它接受单一参数并用于隐式型转换。如果设计不当,可能会引发编译错误或运行时问题。 - **隐式型转换引起的歧义** 当存在多个可能的隐式转换路径时,编译器会报告模糊性错误。例如,如果有两个单参构造函数分别可以将 `int` 和 `double` 型转化为目标型的实例,则可能导致编译失败[^1]。 - **违反常量约束** 如果转换构造函数试图修改通过 `const` 关键字保护的对象状态,则会出现编译期错误。这是因为 `const` 成员函数承诺不对调用对象的状态进行更改[^2]。 - **资源管理中的异常安全问题** 若在构造过程中发生异常而未能妥善处理已分配资源,则会导致内存泄漏或其他未定义行为。正如提到的标准库模板 `std::unique_ptr` 所展示的最佳实践那样,在实现转换构造函数时也应考虑如何优雅地释放潜在资源[^3]。 #### 2. 解决方案探讨 为了规避上述问题,可以从以下几个方面着手改进: - **显式声明构造函数以禁用不必要的隐式转换** 使用关键字 `explicit` 来修饰那些仅希望支持显示转换而非自动推导场景下的构造方法。这样能够有效减少意外产生的多重解释情况的发生几率。 ```cpp class MyClass { public: explicit MyClass(int value); // 显式指定此构造函数不可参隐式转换 }; ``` - **确保成员变量遵循只读约定** 对于需要保持不变性的属性字段设置成 `const` 或者利用 getter 方法返回副本而不是直接暴露可写访问权限给外部使用者。同时记得把相关联的操作标记为 `const` 版本以便兼容更多上下文中合法调用形式的要求。 - **采用智能指针简化生命周期控制逻辑** 避免手动追踪动态创建实体的存在周期复杂度风险,推荐运用现代C++ 提供的各种现成工具如 `std::shared_ptr`, `std::unique_ptr` 等来自动化完成这些繁琐又容易出错的任务。 以下是综合以上建议的一个例子演示: ```cpp #include <memory> #include <string> class ResourceHandle { private: std::unique_ptr<std::string> data; public: explicit ResourceHandle(const char* str) : data(std::make_unique<std::string>(str)) {} ~ResourceHandle() = default; void displayContent() const { if (data && !data->empty()) printf("%s\n", data->c_str()); } }; // 正确使用方式 void exampleUsage(){ ResourceHandle rh("Sample Text"); rh.displayContent(); } ``` #### 总结 通过对转换构造函数合理应用 `explicit` 关键词防止过度泛化;维护好各个组成部分间的相互关系满足一致性原则以及借助高级别的抽象机制提升整体健壮性和可维护水平三管齐下即可很好地应对由其引入的一系列挑战。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值