c ++ - 帮助理解函数和类模板之间的差异

时间:2016-07-10 23:11:42

标签: c++ arrays templates stdvector

我试图实现一个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);

我最终宣布一个对象为一个类&#34; cpparray&#34;其类型为整数。它是否正确? 如果是,那么a.push_back(1)将不起作用,因为它没有引用成员变量而是对象本身,因此它是可以理解的我会得到一个编译时错误说 cpparray中没有名为push_back的成员

但这让我更加难以

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

[2]如何根据我的目标在模板类中初始化此向量并使用它?

2 个答案:

答案 0 :(得分:2)

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

像这样:

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

你所做的是在构造函数中将向量声明为local,将其初始化为size,并在块结束时销毁本地向量。

答案 1 :(得分: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