2014-03-05 257 views
1

我将使用Java开发的纸牌游戏应用程序移植到C++,其中卡对象的排名和套装是通用的(为了能够使用多个特定集),并且卡本身也是通用的(可以打包使用扑克牌,塔罗牌等)。如何声明采用模板类参数的模板类

我得到使用的代码块13.12“的代码块,13.12mingw-设置-TDM-GCC-481”

卡编译在经销商类(模板),它的卡对象(另一个模板)错误类(abstract但工具共享功能性的全部卡片必须具有)

#ifndef CARD_H 
#define CARD_H 

#include <iostream> 
#include <fstream> 
#include <cassert> 
using namespace std; 

enum BJRank 
{ 
    Ace, 
    Two, 
    Three, 
    Four, 
    Five, 
    Six, 
    Seven, 
    Eight, 
    Nine, 
    Ten, 
    Jack, 
    Queen, 
    King, 
    END_OF_RANKS 
}; 
enum GenericSuit 
{ 
    Clubs, 
    Diamonds, 
    Hearts, 
    Spades, 
    END_OF_SUITS 
}; 

template <class U, class V> 
class Card { 
    private: 
     U itsRank; 
     V itsSuit; 
    protected: 
     Card(U newRank = Jack, V newSuit = Spades): 
     itsRank(newRank), itsSuit(newSuit) 
     { 
      //s_numberPlayers++; 
      //cout<<"Number of cards available is: " << s_numberPlayers << "\n"; 
      ofstream myfile ("C:/Temp/cardLogFile.txt", ios::app); 
      if (myfile.is_open()) 
      { 
       myfile << "Card base object constructed\n"; 
      } 
     } 
    public: 
     virtual ~Card() 
     { 
      ofstream myfile ("C:/Temp/cardLogFile.txt", ios::app); 
      if (myfile.is_open()) 
      { 
       myfile << "Card base object destroyed\n"; 
       myfile.close(); 
      } 
     //   if (s_numberPlayers > 0) 
     //    s_numberPlayers--; 
     //   cout<<"Number of cards available is: " << s_numberPlayers << "\n"; 
     } 
     virtual void setRank(U newRank) 
     { 
      this->itsRank = newRank; 
     } 
     virtual void setSuit(V newSuit) 
     { 
      this->itsSuit = newSuit; 
     } 
     virtual const U getRank() 
     { 
      return this->itsRank; 
     } 
     virtual const V getSuit() 
     { 
      return this->itsSuit; 
     } 
}; 


#endif 

一卡派生类(扑克牌)

#ifndef POKERCARD_H 
#define POKERCARD_H 

#include "Card.h" 

template <class U, class V> 
class PokerCard : virtual public Card <U, V> { 
    public: 
     PokerCard(): Card <U, V>() {} 
     PokerCard(U newRank, V newSuit): Card <U, V>(newRank, newSuit) {} 
     ~PokerCard() {} 
    protected: 
     virtual void setRank(U newRank) 
     { 
      Card <U, V> ::setRank(newRank); 
     } 
     virtual void setSuit(V newSuit) 
     { 
      Card <U, V> ::setSuit(newSuit); 
     } 
     virtual const U getRank() 
     { 
      Card <U, V> ::getRank(); 
     } 
     virtual const V getSuit() 
     { 
      Card <U, V> ::getSuit(); 
     } 
     const int getValue(){return 1;} 
}; 

#endif // POKERCARD_H 

的经销商抽象类(从中众议院和玩家将获得)

#ifndef DEALER_H 
#define DEALER_H 

#include <fstream> 
#include <cassert> 
#include <vector> 
#include "PokerCard.h" 
#include "TarotCard.h" 

template < template <class U, class V> class T> 
class Dealer 
{ 
    public: 
     Dealer() {} 
     Dealer(Card<U, V>* cardType) {} 
     virtual ~Dealer() {} 
     virtual const vector <Card<U, V>*> getHand()=0; 
}; 

#endif // DEALER_H 

最后,经销商派生类(创建该卡指针扑克牌对象)

#ifndef DEALERHOUSE_H 
#define DEALERHOUSE_H 

#include "Dealer.h" 


template < template <class U, class V> class T> 
class DealerHouse : virtual public Dealer <T> { 
    private: 
     vector <Card<U, V>* > dealerDeck; 
     Card <U, V> *card; 
    public: 
     DealerHouse(): Dealer<T>() 
     { 
      for (int suitInt = Clubs; suitInt != END_OF_SUITS; suitInt++) 
      { 
       for (int rankInt = Ace; rankInt != END_OF_RANKS; rankInt++) 
       { 
        card = new T((U)rankInt, (V)suitInt); 
        if (card != NULL) 
         dealerDeck.push_back(card); 
        else 
         cout <<"ERROR, card object not created in HEAP" << "\n"; 
       } 
      } 
      ofstream myfile ("C:/Temp/dealerLogFile.txt", ios::app); 
      if (myfile.is_open()) 
      { 
       myfile << "Default Dealer base object constructed:" << "\n"; 
      } 
     } 
     DealerHouse(Card<U, V>* cardType): Dealer<T>(cardType) 
     { 
      dealerDeck.push_back(cardType); 
      ofstream myfile ("C:/Temp/dealerLogFile.txt", ios::app); 
      if (myfile.is_open()) 
      { 
       myfile << "Parameterized Dealer base object constructed:" << "\n"; 
      } 
     } 
     virtual ~DealerHouse() 
     { 
      if (!dealerDeck.empty()) 
      { 
       dealerDeck.clear(); 
      } 
      if (card != NULL) 
      { 
       delete card; 
       card = NULL; 
      } 
      ofstream myfile ("C:/Temp/dealerLogFile.txt", ios::app); 
      if (myfile.is_open()) 
      { 
       myfile << "Dealer object destroyed:" << "\n"; 
       myfile.close(); 
      } 
     } 
     protected: 
     virtual const vector <Card<U, V>*> getHand() 
     { 
      return dealerDeck; 
     } 
}; 

#endif // DEALERHOUSE_H 

我得到这个编译错误的经销商。 h,line“Dealer(Card * cardType){}”: CardGame \ Dealer.h | 16 | error:'U'未在此范围内声明| CardGame \ Dealer.h | 16 |错误:'V'未在此范围内声明|

所以我猜我很差劲的Dealer.h模板参数声明 “模板<模板类T>类经销商”,也是那些在DealerHouse.h,它遵循相同的语法。

有任何帮助吗?我已经检查了回答类似的问题 Template parameters in C++ templates c++ template to template parameter how to declare template of template class

但是当我试图在他们所建议的声明,我得到的错误在DealerHouse.H的“T”型不“卡=新认识T((U)rankInt,(V)suitInt);“。

我明白任何帮助,我真的坚持与...

回答

0

你不实际使用U,VDealerDealerHouse,所以你不需要模板CardPokerCard作为参数,只有一个具体的类象Card<U,V>,这仅仅是T。因此:

template <class T> 
class Dealer 
{ 
    // "Card<U,V>" -> "T" everywhere 
}; 

template <class T> DealerHouse : public Dealer <T> 
{ 
    // "Card<U,V>" -> "T" everywhere 
}; 

你在DealerHouse使用U,V,唯一的一点是线

card = new T((U)rankInt, (V)suitInt); 

它可以只是

card = new T(rankInt, suitInt); 

如果int可以隐式转换为U,V(这是普通的enum的情况),或者如果T具有形式为T(int,int)的构造函数,则反之亦然。

如果你一定需要U,V,例如: Dealer(或DealerHouse),做到这一点的一种方式是在T内提供它们作为特征,例如,

template <class U, class V> 
class Card 
{ 
    // ... 
public: 
    using rank = U; 
    using suit = V; 
}; 

,这样就可以从TDealer “提取” 他们这样

using U = typename T::rank; 
using V = typename T::suit; 

另一种方法是专门Dealer

template <class T> 
class Dealer; 

template <template<class, class> class CARD, class U, class V> 
class Dealer<CARD<U,V> > 
{ 
    using T = CARD<U,V>; 
    // ... 
}; 

在这一点上,你必须再次各类可用T,U,V。这将工作CARDCard,PokerCard,或任何东西。这个更接近你的定义,但也包括U,V作为模板参数,你没有这样做,所以你的编译器找不到它。

数点:

  • 据我所看到的,你不需要在这里virtual继承,所以只说A : public B而非A : virtual public B

  • 你不需要重新定义在派生类中像PokerCardCard的虚拟方法,如果他们只是调用基类Card方法;这是自动完成的。

  • 你真的需要保护setter/getter方法背后的数据吗?

+0

感谢您的详细回复和建议! – silvakle

+0

让我澄清一些事情: - 我使用虚拟继承,以便实现从TarotCard和PokerCard继承的派生Card类。 - 我重新定义了卡的虚拟方法,因为这是应用程序的基础。正如我所说的,我首先在Java中完成了整个事情,我正在谈论像BlackJack和Tarot这样的纸牌游戏。我需要在实现所有其他基础之前(泛型)才能获得基础 - 我想保护来自玩家类(还有待执行)和自动化测试套件类(在此执行TDD)的数据。 – silvakle

+0

将尽快尝试您的建议,并会回到这里... – silvakle

0

你误会参数是什么模板的模板。这里你不需要它们。你只想DealerDealerHouse有两个类型参数,就像Card

相关问题