1
class T : public std::string {  
public:  
    T(char* s) : std::string(s){};  
};  

class X : public T {  
public:  
    X(char* s) : T(s) {};  
    ~X() {};  
};  

template <typename T> T doIt(const T arg);  

int main(int argc, const char* argv[]) {  

    X s("initial string");  
    T s2 = doIt(s);  
    printf("out %s", s2.c_str());  
}  

T doIt(T arg) {  
    arg.append(" appended");  
    return arg;  
};

私のコードの問題は何ですか..出力は次のとおりです...

1>Linking...
1>TemplateStuding1.obj : エラー LNK2001: 未解決の外部シンボル "class X __cdecl doIt(class X)" (??$doIt@VXClass@@@@YA?AVXClass@@V0@@Z)
1 >D:\Programming\cpp\cpp-how-to-program\CppHowToProgram\Release\Test.exe: 致命的なエラー LNK1120: 1 つの未解決の外部

4

3 に答える 3

4

template <class T>(他の人がすでに言及している)の定義が欠落しているという問題を乗り越えた後でdoItも、質問に対する答えが必要になります。

<X extends T>Javaのようにテンプレート引数を作成することは可能ですか?

この質問への答えはノーです。C ++には、Javaのように制約されたジェネリックはありません。C ++ 0xに「概念」と呼ばれるこのような(しかし大きく異なる)ものを追加するという提案がテーブルにありましたが、それは複雑すぎて削除されました。

簡単に言うと、関連するジェネリックを行うには3つの方法があります。

  1. ダックタイピング(Rubyが持っているもの)。これがC++の現在の機能です。クラスがそれと同じメソッドのすべてに応答する場合、class TそれがクラスTから継承されていなくても、法案に適合します。さらに、class Zいくつかのメソッドが欠落しているものを渡そうとするとclass T、テンプレートはそれらを呼び出そうとしません。テンプレートがそれらを呼び出そうとすると、テンプレートが欠落しているメソッドを呼び出そうとした場所にコンパイラエラーが表示されます。(どのテンプレートのインスタンス化が問題の原因であるかは、エラーが発生したときにコンパイラーがインスタンス化しようとしたテンプレートを説明するスタックトレースからわかります。)C ++ではコンパイラーエラーが発生します(Rubyとは異なり実行時エラーです)が、複雑なエラーメッセージです。

  2. 構造型(Scalaが持っているもの)。C ++の概念は、この方向に進むことを目的としていました。クラスが同じメソッドのすべてに応答する場合、class TクラスTから継承されていなくても、そのクラスは法案に適合します。そのクラスが同じメソッドのすべてに応答しない場合は、テンプレート関数であってもエラーになります。欠落しているメソッドを呼び出そうとはしません。テンプレートエラーは、インスタンス化のサイトで報告されます。(C ++のバージョンでは、オブジェクトの演算子をフリー関数として宣言できるため、より複雑になりますが、基本的な考え方は同じです。)

  3. Constrained generics (for lack of a better term -- what Java has). Any class passed to the template must be a subtype of class T. Having the same methods won't cut it unless there's real inheritance. Members of the C++ standardization commitee don't like this -- they prefer #2 over #1 (if they can work out all of the technical issues) and #1 over #3 -- so it will probably never appear in C++.


Would someone else please post an answer untangling this guy's use of class T in this example. He's using it in 2 different ways, and I'm not sure whether his use of T in template <class T> (as opposed to some other letter) was meant to specify a constraint on the types that could be passed. This may be a significant confusion. On the other hand, using T in both places may just be a careless error. I really can't tell.

于 2011-08-11T05:45:41.980 に答える
1

問題は次のとおりです。

template <typename T> T doIt(const T arg);  // <---- declared but not defined

int main(int argc, const char* argv[]) {  
//...
    T s2 = doIt(s);  // <------ it is calling above method (which is visible)
}  

T doIt(T arg) {  // <------ T is `class T`, not `template`, so different method
    arg.append(" appended");  
    return arg;  
};

ここでT doIt(T)afterを定義すると、上記のメソッドmain()の本体を定義していることになります。templateこれは真実ではありません。class T偶然にも;があるため、コンパイラ エラーは発生しません。の定義を渡しますT doIt(T)

使用する場合はtemplate doIt、次のように定義する必要があります。

template<typename T>
T doIt(T arg) {  // <------ T is now `template`; thus same method
    arg.append(" appended");  
    return arg;  
};

template doIt[実際の定義がなく、以下の定義が表示されないため、リンカーエラーが発生することにも注意してくださいmain()。]

于 2011-08-11T05:24:13.533 に答える
0

あなたのコンパイラは、あなたが宣言したが実装していないと不平を言っていますdoIt。今は署名だけですが、実際に定義されているかのように呼び出しています。

余談ですが、このエラーは Java と一体何の関係があるのでしょうか。それともジェネリックでも?

于 2011-08-11T04:59:41.460 に答える