-3

C++ でプログラミングを始めてから 3 年が経ちましたポリモーフィズムが機能していません。 は、 と のオブジェクトをに追加すると オブジェクトにmap<string, Base>変換するため、と で設定した値ではなく、空の文字列を返します。非常に大まかな擬似コードは次のとおりです。ArmyBaseNavyBaseBasemapGetDescription()ArmyBase::SetDescription()NavyBase::SetDescription()

class Base
{ protected:
    string STR__Description;  // Pardon my non-standard style
  public:
    virtual
    string GetDescription()
    { return STR__Description;
    }
    void   SetDescription( string str__Description )
    { STR__Description = str__Description;
    }
}

class ArmyBase: public Base
{ public:
    string GetDescription()
    { return STR__Description + " (Army)";
    }
}

class NavyBase: public Base
{ public:
    string GetDescription()
    { return STR__Description + " (Navy)";
    }
}

メモリリークが発生するようmap<string, Base*>に思えますが、プロジェクトの途中で使用するようにアップグレードしたくありませんshared_ptr派生クラスのインスタンスを適切に「破棄」するコンテナーに格納するとmap、メモリ リークのリスクなしにポリモーフィズムにポインターを使用できるようになりますか?

Base                         base;
ArmyBase                     base_Army;
set<ArmyBase>                set__ArmyBases;
map<string, Base*>::iterator iter_Bases;
map<string, Base*>           map__Bases;
NavyBase                     base_Navy;
set<NavyBase>                set__NavyBases;
...
while( ... )
{   base_Army = ArmyBase();
    base_Navy = NavyBase();
    ...
    set__ArmyBases.insert(                                        base_Army   );
    map__Bases.insert(     pair<string, Base*>( "Boca Raton",    &base_Army ) );
    ...
    set__NavyBases.insert(                                        base_Navy   );
    map__Bases.insert(     pair<string> Base*>( "NAS Pensacola", &base_Navy ) );
    ...
    base = iter_Bases->second;
    std::cout << ..." " << base->GetDescription() << std::endl;
}

からの望ましい出力map__Bases:

Boca Raton ... (Army)
NAS Pensacola ... (Navy)
...
4

5 に答える 5

0

あなたの問題が何であるかを正確に理解するための情報はほとんどありません。しかし、私は利用可能なものから突き刺します。

メモリリークをどのように検出しますか? ArmyBase/に非 POD メンバーが含まれている場合の明らかな問題の 1 つNavyBaseは、ベースから削除するとそのデストラクタが呼び出されないため、Base.

この場合、いくつかの異なるコンテナを使用して提案した2番目のソリューションは、ほぼ間違いなく間違ったアプローチです。派生型ごとに異なるコンテナーを使用すると、そもそもポリモーフィズムの目的全体が無効になります。その上、ループはまったく意味がありません。set__ArmyBases/set__NavyBasesには同一のデフォルトで構築されたオブジェクトが含まれていますが、フレームごとに再初期化されるmap__Bases2 つのグローバル変数base_Navy&へのポインターのみが含まれています。base_Army

于 2013-07-24T08:37:00.087 に答える
0

コード内のばかげた量のタイプミス (常にSSCCEを提供する必要があるのはそのためです) は別として、コードは 2 つの小さな修正後に機能するようになります。

  • Cmpポインタをたどって記述を比較する小さな比較関数オブジェクトを書くBase
  • set<ArmyBase>set<NavyBase>set<Base*, Cmp>とに変更しますset<Base*, Cmp>

コード:

#include <string>
#include <set>
#include <map>
#include <iostream>

using namespace std;

class Base
{ protected:
    string STR__Description;  // Pardon my non-standard style
  public:
    virtual
    string GetDescription() const
    { return STR__Description;
    }
    void   SetDescription( string str__Description )
    { STR__Description = str__Description;
    }
};

class ArmyBase: public Base
{ public:
    string GetDescription() const
    { return STR__Description + " (Army)";
    }
};

class NavyBase: public Base
{ public:
    string GetDescription() const
    { return STR__Description + " (Navy)";
    }
};

class Cmp
{
public:
    bool operator()(Base const* lhs, Base const* rhs) const
    { return lhs->GetDescription() < rhs->GetDescription(); };
};

int main()
{

    Base                         base;
    ArmyBase                     base_Army;
    set<Base*, Cmp>           set__ArmyBases;
    map<string, Base*>      map__Bases;
    map<string, Base*>::iterator         iter_Bases;
    NavyBase                     base_Navy;
    set<Base*, Cmp>          set__NavyBases;


    base_Army = ArmyBase(); 
    base_Navy = NavyBase();

    set__ArmyBases.insert(                   &base_Army   );
    map__Bases.insert(     pair<string, Base*>( "Boca Raton",    &base_Army ) );


    set__NavyBases.insert(                   &base_Navy   );
    map__Bases.insert(     pair<string, Base*>( "NAS Pensacola", &base_Navy ) );

    for (auto b: map__Bases)
        std::cout << b.first << "..." << b.second->GetDescription() << std::endl;
}

出力付きのライブ例

オブジェクトのスライスやメモリ エラーは発生していません。ただし、スコープ オブジェクトへの生のポインタを使用しています (つまり、オブジェクトがスコープ外に出ると、それらの記述子が呼び出されます)。

ポリモーフィック オブジェクトのコンテナを持つための推奨される方法は、 を使用std::map<std::string, std:unique_ptr<Base>>してこれらを割り当てることstd::make_unique<NavyBase>("NAS Penscalola")です。

于 2013-07-24T09:07:58.053 に答える