2016-07-10 7 views
0

要素リストを指定すると、リストから一意の要素を出力するC++プログラムを実装しようとしています。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]私は私が私のベクトルは、任意のデータ型をインスタンス化することができるようにしたいので、テンプレートを使用しようとしている - 文字/フロート/ int型。

[2]私は

cpparray<int>a(10); 

を呼び出すことにより、クラステンプレートを使用してIタイプ整数であるクラス "cpparray" のオブジェクトAを宣言してしまうことを実現します。これは正しいです? はいの場合、a.push_back(1)はメンバ変数を参照するのではなく、オブジェクト自体を参照するため、理解できます。というメンバーがpush_backという名前のコンパイル時にと表示されます。

しかし、これは機能テンプレートとは対照的に、クラステンプレートを使用する際に、[1]理解

に私のためにそれをさらに困難にしている、

[2]どのように私はこれを初期化します私の目的を考えれば、テンプレートクラスのベクトルとそれで動作しますか?あなたのコンストラクタは、メンバーを初期化する初期化リストを使用する必要があります

+0

'push_back'は' array'のメンバ関数として存在するはずです。その後[これ](http://stackoverflow.com/questions/926752/why-should-i-prefer-to-use-member-initialization-list)。あなたのコンストラクタの 'elems'はローカルインスタンスです。 – LogicStuff

+0

正確に。しかし、私は標準のコンテナベクトルを使用しようとしているが、私はクラスの配列を任意の型のベクトルで動作するように一般化しようとする部分を台無しにしている。 – Raaj

+0

私はあなたが、その初期化の試みの場合には、C++入門書でテンプレートの前に来る部分を台無しにしていると言います。そして、* "class template vs function template" *は "class vs function" *のようなものです。 – LogicStuff

答えて

2

、このような

:あなたは、コンストラクタでローカルとしてのベクトルを宣言することですやった

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

は、サイズにINIT、およびローカルベクターはブロックの終わりに破壊された。

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のタイプが​​であるためコンパイラによって推測できます。

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(); 
    } 
}; 

これ: - テンプレート変数 - これはテンプレートクラスのテンプレートメンバ関数を有することも可能です16

ではタイプがCHARであり、配列のサイズは、参照することによりソースをキャプチャすることができ例は、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 
関連する問題