3

他のプロジェクト全体でコードを繰り返す必要がないように、またまだ試したことのない機能、アルゴリズム、テストのために、いくつかのDLLユーティリティプロジェクトを開発してきました。それらのプロジェクトの1つは、私がまだ学んでいる言語であるC ++ / CLIであるため、この質問はばかげているように聞こえるかもしれません。ライブラリプロジェクトはC++/ CLI、F#、C#であるため、C#コンソールアプリケーションを使用してテストします。C ++ / CLIプロジェクトでは機能していなかったため、C ++/CLIコンソールテストプロジェクトを作成しました。それは機能しませんでした、そして私が元のDLL C ++の名前を変更したとき、参照は更新されませんでした。私が(最終的に)問題を発見したとき、私は.vcxprojファイルを変更し、1つのメソッドについてはusingディレクティブを可能にしましたApont<typename T>が、ある種の内部ポインターであるテンプレートクラスについてはそうではありませんでしたが、.NETタイプとは異なりますSystem::IntPtrT*、の代わりにタイプの値を使用しますvoid*

また、(このサイトの投稿から)プロジェクト内で使用したいものを外部で使用する必要があることもわかりました。そうしないと、メタデータでそれらを出力する必要があります。だから私はその目的のために静的ユーティリティに役に立たない静的メソッドを持っています:

static void Funcionalidades()
{
    int i = 10;

    Apont<int> a2 = Apont<int>(i);            // stack
    Apont<int> ^a3 = gcnew Apont<int>(i);     // heap CLR

}

それにもかかわらず、それは機能しません。C ++/CLIテストプロジェクトでの私の主な方法は次のとおりです。

int main(array<System::String ^> ^args)
{
    int y(10);
    Apont<int> a = Apont<int>(y);

    Console::ReadKey();
    return 0;
}

以下にエラーを示します(インテリセンスエラーでコンパイルできることはわかっていますが、とにかく表示します)。

error C2065: 'Apont' : undeclared identifier
error C2062: type 'int' unexpected
IntelliSense: identifier "Apont" is undefined
IntelliSense: type name is not allowed
IntelliSense: expected an expression

なぜこれらのエラーがここにあるのですか?どうすれば修正できますか?

回答や返信をいただければ幸いです。

編集(説明):

  • これらのエラーFuncionalidadesは、DLLプロジェクト内のメソッドでは発生しませんが、テストプロジェクト内のDLLの外部にあるメインメソッドでは発生しません。
  • 私はすべてをヘッダーファイルに書き込んでいます。つまり、すべてのヘッダーファイルにそれぞれの.cppファイルがあるわけではありませんが、すべてのヘッダーは少なくとも1つの.cppファイルに含まれています。
  • 詳細Apont
    • Apontはテンプレートです(T *が内部で使用され、「ジェネリック型パラメーターの間接化は許可されていないため」)。
    • Apontコピーコンストラクターがあるので、動作するApont<int> a = Apont<int>(someInt)はずです。
    • Apont<int> a(someInt)動作しません。
    • Apontある種の内部ポインタです。また、関連性がないため、コード全体を投稿しませんでした。変数の名前を翻訳する必要があり、エラーが発生する可能性がありますが、簡単に修正できますが、気が散るだけです。

NTH EDIT(ここで、「n」は私が知らない番号です):

Apontあなたが長い間不平を言ってきたのコード:

    template<typename T> public ref class Apont sealed : public IDisposable
    {
        bool eliminado;
        T *pointer;

        /*void Dispose(bool tudo)
        {
            if (!eliminado)
            {
                if (tudo)
                {
                    ~Apont();
                }
                else
                {
                    !Apont();
                }
            }
        }*/
        !Apont() // finalizador: limpa os recursos "unmanaged"
        {
            delete pointer;
            pointer = nullptr;
            eliminado = true;
        }

    public:
        Apont(T &valor)
        {
            pointer = &valor;
            eliminado = false;
            ErroSeNulo = false;
            ErroSeEliminado = true;
        }
        Apont(T &valor, bool erroSeEliminado, bool erroSeNulo)
        {
            pointer = &valor;
            eliminado = false;
            ErroSeEliminado = erroSeEliminado;
            ErroSeNulo = erroSeNulo;
        }
        Apont(Apont<T> %outroApont)
        {
            this->pointer = &outroApont
        }

        property bool ErroSeEliminado;
        property bool ErroSeNulo;
        property T Valor
        {
            T get()
            {
                if (pointer != nullptr)             
                    return *pointer;
                else if (eliminado && ErroSeEliminado)
                    throw gcnew ObjectDisposedException("O objeto já foi pelo menos parcialmente eliminadao.");
                else if (ErroSeNulo)
                    throw gcnew NullReferenceException();
                else
                    return 0;
            }
        }

        /*
        Apont operator ~(/*T valor* /)
        {
            // este operador tem de ser declarado fora desta classe 
        }*/
        T operator !(/*Apont apont*/)
        {
            return Valor;
        }
        void operator =(Apont<T> outroApont)
        {
            pointer = outroApont;
            ErroSeEliminado = outroApont.ErroSeEliminado;
            ErroSeNulo = outroApont.ErroSeNulo;             
        }
        template<typename U> void operator =(Apont<U> outroApont)
        {
            pointer = safe_cast<T>(outroApont.pointer);
            ErroSeEliminado = safe_cast<T>(outroApont.ErroSeEliminado);
            ErroSeNulo = safe_cast<T>(outroApont.ErroSeNulo);
        }
        /*
        void operator =(T *&outroPointer)
        {
            pointer = outroPointer;
        }
        template<typename U> void operator =(U *&outroPointer)
        {
            pointer = safe_cast<T>(outroPointer);
        }*/
        void operator =(T *outroPointer)
        {
            pointer = outroPointer;
        }
        template<typename U> void operator =(U *outroPointer)
        {
            pointer = safe_cast<T>(outroPointer);
        }


        ~Apont() // destruidor: limpa todos os recursos
        {               
            this->!Apont();
        }

        // Error C2605: 'Dispose': this method is reserved within a managed class
        // O código será gerado automaticamente a partir do finalizador e do destrutor
    };

    template<typename T> Apont<T> operator ~(T &valor)
    {
        return gcnew Apont<T>(valor);
    }
4

5 に答える 5

3

表示されるエラーは、通常、クラスの宣言が欠落しています。これは通常、ヘッダー内のコードがヘッダーで保護されている場合に発生します。

これはどのように起こったのですか?

Funcionalidades 内に Apont ヘッダーを含めてから、Apont に Funcionalidades ヘッダーを含めると、問題が発生します。これは、Funcionalidades を含める前に Apont をメインに含める場合に、Funcionalidades ヘッダーに Apont の宣言がないために発生します。

次に、最初に Apont を含めると、ヘッダー ガードが有効になります。次に、Apont も含む Funcionalidades が含まれます。ヘッダー ガードが既に有効になっているため、Funcionalidades ヘッダーには Apont 宣言がありません。同時に、Apont の宣言は、対応する Apont のヘッダー ファイルでまだ開始されていませんでした。ライブラリのコンパイル時にそのような依存関係がないため、main でこの問題が原因でコンパイルできません。

どうすれば修正できますか?

Apont の使用を cpp コードの Funcionalidades 実装内に移動し、依存関係のないヘッダー ファイルを保持します。

于 2013-04-12T05:51:53.193 に答える
1

お返事に時間がかかって申し訳ありません。問題を解決するのに役立つポイントがいくつかあります。- テンプレート クラスがsealとして宣言されている: これは、それを基本クラスとして使用できないことを意味します (テンプレート化されたクラスの主な理由とは逆です)。少なくともそれは必要ないので、削除する価値があるかもしれません. - 第二に、さらに重要なことに、C++ テンプレートはコンパイル時に評価されるため、指定されたインスタンスが宣言されていないため、Apont の評価はなく、DLL にコンパイルされません。特定のバージョンのテンプレート クラスを有効にするには、UtilCMM.hファイルの最後に次を追加します。

  • class template Apont<int>;
  • class template Apont<float>;
  • class template Apont<double>;

これは、C++ ではテンプレートがマクロと同様にコンパイル時にプリプロセッサによって展開されるという事実によるものですが、明示的に使用されたバージョンのみがコンパイル時に処理されます。これは大きな長所と短所の両方です。(他の C++ プログラマーとのコンセンサスで) 私がいつも見つけた解決策は、次のいずれかです。

  • dll でエクスポートする必要があるバージョンを明示的にインスタンス化します。
  • テンプレートを含むヘッダー ファイルを提供する

同じことを達成する他の方法がある場合、私はまだそれらに遭遇していません。悲しいことに、これらはテンプレートの制限です。

コンパイルすると、3 つの特定のバージョンが利用可能になるはずです。DLL に含めたいタイプごとに追加するだけです。申し訳ありませんが、以前にこれを見つけられませんでした。完全なコードを見たときに両方とも飛び出しました。プロジェクトをコンパイルするだけで、自分で変更を試すことができます (私のバージョンの VS は、あなたのバージョンの vcproj ファイルをロードしません。典型的)。

于 2013-04-19T07:25:41.890 に答える
1

外部で使用したいものをプロジェクト内で使用する必要がある

これが当てはまる場合、静的関数をどこかで呼び出しましたか? 呼び出されていない関数が最適化される可能性があります。

于 2013-04-10T18:20:51.753 に答える
1

名前空間の using ステートメントが欠落している可能性はありますか? メイン メソッドに適切な using ステートメントがあることを確認してください。また、main メソッドを含むプロジェクトが Apont を含むプロジェクトを参照するように、参照を追加したことを確認してください。

于 2013-04-17T05:39:09.963 に答える
1

「Apont」を知らないと不平を言うだけです。それが何であるかもわかりません。コードを投稿していません。それの任意のバージョンを宣言するだけです:

generic<typename T>
public ref class Apont {
    T value;
public:
    Apont(T init) : value(init) {}
};

static void Funcionalidades()
{
    int i = 10;

    Apont<int> a2(i);                      // stack
    Apont<int> ^a3 = gcnew Apont<int>(i);  // heap CLR

}

「a2」の変更されたコードに注意してください。参照型のコピー コンストラクターは避けてください。再び主に:

    Apont<int> a(y);
于 2013-03-09T16:33:49.827 に答える