【问题标题】:c++ - help understanding differences between function and class templatesc++ - 帮助理解函数和类模板之间的区别
【发布时间】:2016-07-10 23:11:41
【问题描述】:

我正在尝试实现一个 C++ 程序,给定一个元素列表,从列表中打印出唯一的元素。

我比 C++ 更了解 C,但我现在才开始实际(编码)C++。

我只阅读了 C++ 概念什么是模板,我对函数模板很满意,但我只是阅读了类模板,我想我对在哪里使用哪个模板感到困惑,因为它适用于下面的场景。

这是我到目前为止所写的(*请注意,函数 isUnique 应该做其他事情,但我现在只在其中编写可验证的操作):

cppArrays.h

#include <iostream>
#include <cstdlib>
#include <vector>
#include <string>
using namespace std;

template <class T> class cpparray{
private:
    int size;
    vector<T> elems;
public:
    cpparray(int);
    ~ cpparray();
    int isUnique(T arr);
};


template <class T> cpparray<T>::cpparray(int size)
{
    vector<T> elems(size);
    cout << "Object created with size " << elems.size()<< "\n"<< endl;
}
template <class T> cpparray<T>::~cpparray()
{
    cout << "Object del\n" << endl;
}

template <class T> int cpparray<T>::isUnique(T arr)
{
    return arr.size();
}

cppArrays.cc

#include "cppArrays.h"

int main()
{
    cpparray<int> a(10) ;
    //a.push_back(1);
    //a.push_back(2);
    //cout << a.size() << a.begin() << a.end() << endl;
    int b = isUnique(a);
    return 0;
}

详情

[1] 我正在尝试使用模板,因为我希望我的 vector 能够被实例化为任何数据类型 - char/float/int。

[2] 我意识到在使用类模板时,通过调用

cpparray<int>a(10);

我最终声明了一个类型为整数的“cpparray”类的对象。它是否正确? 如果是,那么a.push_back(1) 将不起作用,因为它不引用成员变量而是对象本身,因此这是可以理解的>.

但这让我更难

[1] 了解何时使用 class 模板而不是 function 模板,

[2] 鉴于我的目标,我如何在模板类中初始化这个向量并使用它?

【问题讨论】:

  • push_back 应该作为array 的成员函数存在。然后thiselems 在你的构造函数中是一个本地实例。
  • 没错。但是我正在尝试使用 std 容器向量,但我搞砸了我尝试泛化类数组以使用任何类型数据的向量的部分。
  • 在初始化尝试的情况下,我会说你搞砸了 C++ 入门书中模板之前的部分。而问"class template vs function template"有点像"class vs function"
  • @Raaj -- 请不要打电话给你的自制班array。 C++ 中已经有一个std::array 类。
  • @PaulMcKenzie 指出。会叫它别的东西。谢谢!那仍然不能帮助我弄清楚我做错了什么:/

标签: c++ arrays templates stdvector


【解决方案1】:

您的构造函数应该使用初始化列表来初始化成员,

像这样:

template <class T> array<T>::array(int sz) :  size(sz), elems(sz)
{
    cout << "Object created with size " << elems.size()<< "\n"<< endl;
}

您所做的是在构造函数中将向量声明为本地向量,将其初始化为大小,并且本地向量在块结束时被销毁。

【讨论】:

    【解决方案2】:

    当您需要具有编译时变量属性的通用类型 时,请使用类模板。模板参数可以是类型常量,例如

    template<typename T, size_t Size>
    class MyArray {
        T elements_[Size];
    public:
        MyArray() {}
        // ...
    };
    

    如果希望编写可应用于各种类型/参数的通用函数,请使用函数模板:

    #include <cstdio>
    #include <iostream>
    
    template<size_t BufSize, typename... Args>
    int strprintf(char(&buf)[BufSize], const char* fmt, Args&&... args)
    {
        static_assert(BufSize > 0, "Buffer too small");
        static_assert(BufSize < (1 << 31), "Buffer too large");
        return snprintf(buf, BufSize, fmt, std::forward<Args>(args)...);
    }
    
    int main() {
        char buf[16];
        int printed = strprintf(buf, "hello world %s so long", "oversized load");
        std::cout << buf << "\n";
    }
    

    http://ideone.com/SLUQX3

    以上是如何替换旧的 vsnprintf 转发 printf 类型函数之一的示例;在编译时完成所有的跑腿工作会大大提高效率。

    BufSize可以被编译器推导出来,因为buf的类型是char[16];它可以通过引用捕获源,类型为char,数组大小-模板变量-为16。

    模板类的模板成员函数也是可能的:

    template<typename T>
    class Foo {
        T t_;
    public:
        Foo() : t_() {}
        Foo(const T& t) : t_(t) {}
    
        template<typename RhsT>
        bool is_same_size(const RhsT& rhs) {
            return t_.size() == rhs.size();
        }
    };
    

    此示例仅适用于 T 和 RhsT 都具有 size() 成员函数的实例,导致以下结果:

    Foo<vector<int>> fvi;
    Foo<list<double>> fld;
    fvi.is_same_size(fld);  // fine
    Foo<int> fi;
    fvi.is_same_size(fi);  // compiler error
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-20
      • 1970-01-01
      • 1970-01-01
      • 2011-08-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多