Dav*_*les 0 c++ java generics templates
我在Java中有一小部分算法用于播放多个回合制游戏,例如TicTacToe,Othello,Checkers等.我使用Java Generics(自我绑定类型)来使用相同的算法而不必为每场比赛专门改变它们.我在这里没有显示使用自绑定类型的原因,但是评估函数需要它.
public interface Game<GAME extends Game<GAME>> {
GAME copy();
int getCurPlayer();
...
}
public class TicTacToe implements Game<TicTacToe> {
...
@Override
public TicTacToe copy() {
...
}
@Override
public int getCurPlayer() {
...
}
...
}
Run Code Online (Sandbox Code Playgroud)
今天,为了学习,我尝试使用C++模板将我的Java代码移动到C++.
这是我的方法,显然它没有用.
Game.h
template <typename T>
class Game
{
public:
virtual T copy() const = 0;
virtual int cur_player() const = 0;
...
};
Run Code Online (Sandbox Code Playgroud)
TicTacToe.h
class TicTacToe : public Game<TicTacToe>
{
public:
virtual TicTacToe copy() const;
virtual int cur_player() const;
...
};
Run Code Online (Sandbox Code Playgroud)
TicTacToe.cpp
TicTacToe TicTacToe::copy() {
...
}
int TicTacToe::cur_player() {
...
}
Run Code Online (Sandbox Code Playgroud)
当我尝试编译时,我得到的错误是:
out-of-line definition of 'copy' does not match any declaration in 'TicTacToe'
out-of-line definition of 'cur_player' does not match any declaration in 'TicTacToe'
Run Code Online (Sandbox Code Playgroud)
...对于其他每个纯虚函数都是一样的.
您的定义也需要const适用于它们.CRTP,在C++(奇怪的重复模板模式)中已知是完全有效的C++.
但是,这里没有必要virtual,CRTP用于静态调度功能并自动实现功能.
template <typename T>
class Game
{
T& crtp_cast() { return *static_cast<T*>(this); }
const T& crtp_cast() const { return *static_cast<const T*>(this); }
public:
T copy() const { return crtp_cast(); }
int cur_player() const { return crtp_cast().cur_player(); }
...
};
Run Code Online (Sandbox Code Playgroud)
注意,在这种情况下,派生类并没有需要执行"复制"功能,拷贝构造函数都会被自动"复制"来调用.但是,在一般情况下,由于模板是鸭子类型,所以不必做这种事情,通常你只需使用标准模板.与Java的Generics不同,C++的模板与继承无关 - 您可以实例化的类型不必从公共接口继承.
template<typename Game> void f(const Game& g) {
std::cout << g.cur_player();
}
class X {
public:
int cur_player() const { return 1; }
};
class Y {
public:
int cur_player() const { return 2; }
};
int main() {
f(X());
f(Y());
}
Run Code Online (Sandbox Code Playgroud)