1

Tokenという親クラスがあります

ErrorToken と EndToken の 2 つの子クラスがあります。 これらのクラスのそれぞれが、他の のオブジェクトを作成し、関数呼び出しを介してそれを返すことができる必要があります。それぞれに独自の個別のヘッダー クラスがあります。

したがって、ErrorToken は新しい EndToken オブジェクトを作成して返すことができる必要があり、EndToken は新しい ErrorToken オブジェクトを作成して返すことができる必要があります。

これを成功させる最善の方法は何でしょうか? プラグマを一度も使用したくないので、可能な限りクロスコンパイラ互換であることが望ましいです。(しかし、それは本質的に私が探しているものです)。

理想的には、このようなことができるようになりたいのですが...

#ifndef ErrorToken
#include "ErrorToken.h"
#endif

しかし、それは決してうまくいかないようです(私の推測では、それは間違っていると思いますか?誰かが理由を理解するのを手伝ってくれますか?)。

前方宣言の私の理解は、それが関数のシグネチャとポインターでのみ機能するということです(それは正しいですか?)、コンストラクターを実行できるようにするために必要なので、私の状況では機能しないと思います...または機能しますコンパイラは、コンストラクタがその時点で終了することを認識する必要があるだけですか?

4

2 に答える 2

2

さて、前方宣言を使用してください。あなたが言ったように、そこには何百万もの説明があり、今では何百万と1があります:

ErrorToken.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; }
}

基本ポインターを介してオブジェクトを処理するだけなので、ヘッダーは他の派生クラスについて何も知る必要はありません。(コードをファイルに分割するのはあなたに任せます。各ブロックは別のファイルになります。)

于 2013-09-12T08:31:04.897 に答える
1

なぜあなたの

#ifndef ErrorToken

違う?まず、ヘッダーファイルに入れ、次に何かが実際に定義されていることを確認します ErrorToken


ガードと前方宣言を含めると、この穴から抜け出すことができます。

//"ErrorToken.h"
#ifndef ERROR_TOKEN_INCLUDED
#define ERROR_TOKEN_INCLUDED

class EndToken;

class ErrorToken
{
public:
    EndToken DoSomething();
};
#endif

//"EndToken.h"
#ifndef END_TOKEN_INCLUDED
#define END_TOKEN_INCLUDED
class ErrorToken;

class EndToken
{
public:
    ErrorToken DoSomething();
};
#endif

循環依存関係については、以前にいくつかの議論がありました: herehere、およびhere
cpp ファイルで作業の大部分を行うことができます。ここで、他のヘッダーを含めます。これにより、前方宣言だけでなく、完全なクラス定義が認識されます。 、そしてそれを使用することができます。
ただし、まず一歩下がって、「お互いのことを本当に知る必要があるのか​​」と尋ねてください。

于 2013-09-12T08:32:44.617 に答える