2017-12-29 41 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); 
} 

내가 컴파일 오류를 얻을

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

내가 addCust라는 한 길을 잘못하지만 여전히 호출하는 같은 생각을받지 알고있다. 이 문제를 해결하기위한 힌트가 있습니까?

또한 에이전트 클래스를 올바르게 작성한 방법이 있습니까?

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

정적 다형성 (템플릿). 에이전트 클래스는 고객 유형에 템플릿, 그래서 벡터는 고객의 하나 개의 유형을 포함 할 수 있지만 특정 고객 유형에 대해 특정 에이전트를 쉽게 만들 수 있습니다 :

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