2017-12-29 62 views
0

WindowsのC++でオブザーバテンプレートサンプルを作成しています。C++サンプルオブザーバテンプレートクラスエラー

ここには、顧客のリストを持つエージェントがあります。エージェントのエンティティ(変数x)が変わるたびに、それについて顧客に通知し、xの値を顧客に渡します。顧客は、この値をそれぞれの変数に格納します。

以下のコードでは、エージェントはサブジェクトとして機能し、顧客はオブザーバーとして機能します。 エージェントはエージェントテンプレートクラスから作成され、顧客は顧客テンプレートクラスから作成されます。

template <typename T> 
class customer      // acts as base observer class 
{ 
    char name[50]; 

public: 
    customer() 
    { 
     cout << __FUNCTION__ "(): " << "DEFAULT CONS\n"; 
    } 

    customer(char* nm) 
    { 
     strcpy_s(name, nm); 
     cout << __FUNCTION__ "(): " << "name set to " << name << "\n"; 
    } 

    char * getName() 
    { 
     return(name); 
    } 

    virtual void update(int c) 
    { 

    } 
}; 

class customerC: public customer<customerC> 
{ 
    int c; 
public: 
    customerC() 
    { 
     cout << __FUNCTION__ "(): " << "DEFAULT customerc cons\n"; 
    } 

    customerC(char* nm):customer<customerC>(nm) 
    { 
     cout << __FUNCTION__ "(): " << "customer is " << getName() << "\n"; 
    } 

    void update(int val) 
    { 
     cout << __FUNCTION__ "(): c to " << c << "\n"; 
     c = val; 
    } 
}; 

class customerD: public customer<customerD> 
{ 
    int d; 
public: 
    customerD() 
    { 
     cout << __FUNCTION__ "(): " << "DEFAULT customerd cons\n"; 
    } 

    customerD(char* nm):customer<customerD>(nm) 
    { 
     cout << __FUNCTION__ "(): " << "customer is " << getName() << "\n"; 
    } 

    void update(int val) 
    { 
     cout << __FUNCTION__ "(): c to " << d << "\n"; 
     d = val; 
    } 

}; 



template<typename T> 
class agent 
{ 
    char name[50]; 
    int x; 

protected: 
    vector<customer<T>*> custList; 

public: 
    agent() 
    { 
     cout << __FUNCTION__ "(): " << "DEFAULT agent cons\n"; 
    } 

    virtual void setx(int c) 
    { 
     cout << __FUNCTION__ "(): " << "Setting x to " << c << "\n"; 

////  x = c; 
////  notifyObs(); 
    } 

    virtual void getx() 
    { 
     cout << __FUNCTION__ "(): " << "x = " << x << "\n"; 
    } 

    void addCust(customer<T>* cobj) 
    { 
     cout << __FUNCTION__ "(): " << "Adding customer " << cobj->getName() << " to list.\n"; 
     custList.push_back(cobj); 
    } 

    void showCust() 
    { 
     cout << __FUNCTION__ "(): " << "Customers are:\n"; 

     if(custList.empty()) 
      cout << "\n\nYou have no items."; 
     else 
     { 
      vector<customer<T>*>::iterator cs; 
      for(cs = custList.begin(); cs != custList.end(); ++cs) 
      { 
       cout << (*cs)->getName() << "\n"; 
      } 
     } 
    } 

    int notifyObs() 
    { 
     cout << __FUNCTION__ "(): " << "Customers notified are:\n"; 

     if(custList.empty()) 
      cout << "\n\nYou have no items."; 
     else 
     { 
      vector<customer<T>*>::iterator cs; 
      for(cs = custList.begin(); cs != custList.end(); ++cs) 
      { 
       cout << (*cs)->getName() << "\n"; 
       (*cs)->update(x); 
      } 
     } 

     return 0; 
    } 
}; 

class agentS: public agent<agentS> 
{ 
    int x; 

public: 
    agentS() 
    { 
     cout << __FUNCTION__ "(): " << "DEFAULT agentS cons\n"; 
    } 

    void setx(int c) 
    { 
     cout << __FUNCTION__ "(): " << "Setting x to " << c << "\n"; 

     x = c; 
     notifyObs(); 
    } 

    void getx() 
    { 
     cout << __FUNCTION__ "(): " << "x = " << x << "\n"; 
    } 
}; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    customerC cobj("c1"); 
    customerD dobj("c2"); 

    agentS agS; 

    agS.addCust(cobj); 
//// agS.addCust<customer<customerC>>(cobj); 
//// agS.addCust(dobj); 
    agS.showCust(); 
    agS.setx(4); 

    return(0); 
} 

私はaddCustが間違っていると呼ばれるが、それを呼び出すためにと、まだすべてのアイデアを取得していない方法を知って

error C2664: 'agent<T>::addCust' : cannot convert parameter 1 from 'customerC' to 'customer<T> *' 

コンパイル・エラーが発生します。 この問題を解決するためのヒント?

また、エージェントクラスを正しく作成した方法は?

class agentS: public agent<agentS> 

私はオブザーバオブジェクトを渡すaddCust()関数を呼び出します。

+0

* 'addCust'はポインタを要求しますが、' cobj'はポインタではありません。私には、正確にどこに変更を加えて一致させるべきか明確ではありません。 –

答えて

1

このようにagentSクラスを作成すると、addCustの有効な署名はvoid addCust(customer<agentS>* cobj);になります。ただし、顧客クラスはエージェントタイプにテンプレート化されていません(実際にテンプレート化される理由はないようです)。

動的多型(継承と顧客との仮想関数)と静的多型(あるタイプの顧客のベクトルを作成するためのテンプレート)が混在しているようです。これらのオプションを単独で使用する方が意味があります。

動的多型(継承)。あなたは、基本クラスのポインタを格納することで、同じコンテナ内の顧客のさまざまな種類を格納し、同じ方法でそれらを踏むために顧客の基底クラスと仮想関数を使用することができます。

struct customer {}; 
struct customerC : customer {}; 
struct customerD : customer {}; 

struct agent 
{ 
    void addCust(customer* customer) { ... } 

    std::vector<customer*> custList; 
}; 

int main() 
{ 
    agent a; 
    customerC c; 

    a.addCust(&c); 
} 

静的多型(テンプレート)。エージェントクラスは顧客タイプにテンプレート化されているため、ベクターには1つのタイプの顧客のみが含まれますが、特定の顧客タイプに対して特定のエージェントを作成するのは簡単です:

struct customer {}; 
struct customerC : customer {}; 
struct customerD : customer {}; 

template<CustomerT> 
struct agent 
{ 
    void addCust(CustomerT* customer) { ... } 

    std::vector<CustomerT*> custList; 
}; 

int main() 
{ 
    agent<customerC> a; 
    customerC c; 

    a.addCust(&c); 
}