好吧,使用前向声明。正如你所说,那里有数百万种解释,现在有数百万零一个:
错误令牌.h:
#ifndef H_ERROR_TOKEN
#define H_ERROR_TOKEN
#include "Token.h"
class EndToken;
class ErrorToken : public Token
{
public:
EndToken makeEndToken();
};
#endif
EndToken.h:
#ifndef H_END_TOKEN
#define H_END_TOKEN
#include "Token.h"
class ErrorToken;
class EndToken : public Token
{
public:
ErrorToken makeErrorToken();
};
#endif
在每个实现文件中,您现在可以愉快地包含两个头文件:
#include "ErrorToken.h"
#include "EndToken.h"
ErrorToken EndToken::makeErrorToken()
{
return ErrorToken(); // example
}
EndToken ErrorToken::makeEndToken()
{
return EndToken();
}
正如@James Kanze 指出的那样,您可能对 C++ 的工作原理感到困惑。以下代码可能更符合您对 Java 的期望,并且在多态设计方式中更有意义:
class Token { virtual ~Token() {} };
class ErrorToken : public Token
{
std::unique_ptr<Token> makeEndToken();
};
class EndToken : public Token
{
std::unique_ptr<Token> makeErrorToken();
};
std::unique_ptr<Token> EndToken::makeErrorToken()
{
return { new ErrorToken; }
}
std::unique_ptr<Token> ErrorToken::makeEndToken()
{
return { new EndToken; }
}
由于您仅通过基指针处理对象,因此标头不需要了解有关其他派生类的任何信息。(我留给您将代码细分为文件;每个块都进入一个单独的文件。)