国际象棋作业:Piece类静态Factory成员函数实现求助
解决Piece::Factory函数的高效实现问题
嘿,我来帮你搞定这个Factory函数的实现难题!既然要求不能用Clone、要高效避免多分支,那最适合的方案就是用函数指针映射表——通过数组直接索引创建函数,实现O(1)的查找效率,完全避开冗长的switch/if-else链。
核心思路
我们可以在Piece类的实现文件(比如Piece.cpp)里定义一组辅助创建函数,再用一个静态数组把PieceChar枚举值和对应的创建函数关联起来。因为PieceChar是基于char的枚举,直接用字符值做数组索引,效率拉满。
具体实现步骤
1. 定义辅助函数类型和创建函数
先在Piece.cpp里用匿名命名空间包裹所有辅助代码(避免污染全局命名空间),定义创建每个棋子的静态函数:
namespace { // 定义创建函数的指针类型:接受Position引用,返回Piece* using PieceCreator = Piece*(*)(const Position&); // 白兵的创建函数 static Piece* CreateWhitePawn(const Position& pos) { return new Pawn(Colour::WHITE, pos); } // 黑兵的创建函数 static Piece* CreateBlackPawn(const Position& pos) { return new Pawn(Colour::BLACK, pos); } // 同理,为其他棋子类型实现创建函数(假设Knight、Bishop等子类已存在) static Piece* CreateWhiteKnight(const Position& pos) { return new Knight(Colour::WHITE, pos); } static Piece* CreateBlackKnight(const Position& pos) { return new Knight(Colour::BLACK, pos); } static Piece* CreateWhiteBishop(const Position& pos) { return new Bishop(Colour::WHITE, pos); } static Piece* CreateBlackBishop(const Position& pos) { return new Bishop(Colour::BLACK, pos); } static Piece* CreateWhiteRook(const Position& pos) { return new Rook(Colour::WHITE, pos); } static Piece* CreateBlackRook(const Position& pos) { return new Rook(Colour::BLACK, pos); } static Piece* CreateWhiteQueen(const Position& pos) { return new Queen(Colour::WHITE, pos); } static Piece* CreateBlackQueen(const Position& pos) { return new Queen(Colour::BLACK, pos); } static Piece* CreateWhiteKing(const Position& pos) { return new King(Colour::WHITE, pos); } static Piece* CreateBlackKing(const Position& pos) { return new King(Colour::BLACK, pos); } // EMPTY对应的创建函数:返回nullptr static Piece* CreateEmpty(const Position&) { return nullptr; } } // 匿名命名空间
2. 初始化静态映射数组
接着在同一个匿名命名空间里,创建一个静态数组,把PieceChar的字符值和对应的创建函数绑定:
namespace { // ... 上面的创建函数 ... // 静态映射数组:用char值作为索引,直接定位创建函数 static const PieceCreator creatorMap[256] = { nullptr, // 默认值,处理未定义的字符 // 手动初始化枚举对应的位置 [static_cast<char>(PieceChar::WHITE_PAWN)] = CreateWhitePawn, [static_cast<char>(PieceChar::WHITE_KNIGHT)] = CreateWhiteKnight, [static_cast<char>(PieceChar::WHITE_BISHOP)] = CreateWhiteBishop, [static_cast<char>(PieceChar::WHITE_ROOK)] = CreateWhiteRook, [static_cast<char>(PieceChar::WHITE_QUEEN)] = CreateWhiteQueen, [static_cast<char>(PieceChar::WHITE_KING)] = CreateWhiteKing, [static_cast<char>(PieceChar::BLACK_PAWN)] = CreateBlackPawn, [static_cast<char>(PieceChar::BLACK_KNIGHT)] = CreateBlackKnight, [static_cast<char>(PieceChar::BLACK_BISHOP)] = CreateBlackBishop, [static_cast<char>(PieceChar::BLACK_ROOK)] = CreateBlackRook, [static_cast<char>(PieceChar::BLACK_QUEEN)] = CreateBlackQueen, [static_cast<char>(PieceChar::BLACK_KING)] = CreateBlackKing, [static_cast<char>(PieceChar::EMPTY)] = CreateEmpty, }; } // 匿名命名空间
3. 实现Factory函数
最后,在Piece.cpp里实现静态Factory函数:
Piece* Piece::Factory(PieceChar pieceChar, const Position& pos) { // 把枚举转成unsigned char,避免负索引问题 unsigned char charVal = static_cast<unsigned char>(pieceChar); PieceCreator creator = creatorMap[charVal]; // 如果找到对应的创建函数,调用它;否则返回nullptr if (creator) { return creator(pos); } return nullptr; }
方案优势
- 高效:数组索引是O(1)操作,比switch/if-else链快得多,尤其适合棋子类型固定的场景。
- 符合要求:完全没有用到Clone函数,所有创建逻辑都是直接new对应子类实例。
- 可维护:如果后续新增棋子类型,只需要添加对应的创建函数和映射项,不需要修改Factory函数本身。
- 不修改类声明:所有辅助代码都在实现文件里,完全不碰头文件的类声明,满足你的限制条件。
内容的提问来源于stack exchange,提问作者clarence ng
相关产品推荐
相关产品推荐

