4

序文:私は約 1 か月前に大学で C++ の勉強を始めました。これは課題用です。私たちは今、じっと見つめていて、多くの高度な概念を理解していません.

tl;dr: .があるとしましょうBook。のBook動的配列ですPages*。それぞれPageWrittenPageまたは になりDrawnPageます。すべてを印刷したい場合Pagesは、virtual method. を印刷したいだけの場合、DrawnPagesまたはWrittenPages内で何らかのフィルタリングを行う必要がありますBook。どうやってするか?今typeidのところsubtype、それぞれのPage. 迅速かつ簡単なことを急いでいる場合は、@CantChooseUsernames による承認済みの回答をご覧ください。私の問題ではうまく機能しています。さらに専門知識がある場合は、@ nm による新しい回答についてどう思うかお聞きしたいと思います。現在受け入れられている回答が、ディスカッションに何か新しい意味のあるものをもたらすと思われる場合は、コメントしたり、自分の回答を投稿したりすることを思いとどまらせないでください。


元の質問:

TheseObj と TheseObj のスーパークラスであるクラス MyObj があります。

Class TheseObj : public MyObj {
}

Class ThoseObj : public MyObj {
}

MyObj インスタンスへのポインターを持つ std::vector と、これらのオブジェクトのみをリストする非静的メソッドを含む別のクラスがあります。

Class MyClass {
    private:
    vector<MyObj*> vec;

    public:
    void listTheseObj() {
        for each (myObj* obj in vec) {
            if(typeid(*obj) == typeid(theseObj)) {
                cout << *obj << endl;
            }
        }
    }
}

すべての演算子はすでに正しくオーバーロードされています。

これはうまくいきます。問題は、同じことをする必要がある場所がもっとたくさんあるということです。そのため、次のようなことを行うために、GENERIC ベクトルとクラス TYPE を受け取ることができるテンプレート メソッドが必要です。

listObjects(class_name_here, vec);

私はなんとか作成しました:

template <class T>
void listObjectsOfOneType(const type_info& class_name_here, const vector<T*>& vec) {
    for each (T* obj in vec) {
        if(typeid(*obj) == typeid(class_name_here)) {
            cout << *obj << endl;
        }
    }
}

確信はないけど:

  1. テンプレートの方法が正しい場合
  2. どうやって呼べばいいの

お時間をいただきありがとうございます。

4

3 に答える 3

4

おそらく TypeID の使用は避けたいと思います。

#include <iostream>
#include <vector>
#include <typeinfo>

template <class T, class U>
void ListObjects(std::vector<U*> &vec)
{
    for (U* obj : vec)
    {
        if (typeid(*obj) == typeid(T))
        {
            obj->Print();
            std::cout<<"\n";
        }
    }
}

class Parent
{
    public:
        Parent() {std::cout<<"Parent Constructed\n";}
        virtual ~Parent() {std::cout<<"Parent Destructed\n";}

        virtual void Print(){std::cout<<"Parent\n";}
};

class Brother : public Parent
{
    public:
        Brother(){std::cout<<"Brother Constructed\n";}
        virtual ~Brother(){std::cout<<"Brother Destructed\n";}
        void Print() override {std::cout<<"Brother\n";}
};

class Sister : public Parent
{
    public:
        Sister(){std::cout<<"Sister Constructed\n";}
        virtual ~Sister(){std::cout<<"Sister Destructed\n";}
        void Print() override {std::cout<<"Sister\n";}
};

int main()
{
    std::vector<Parent*> Objects;
    Objects.push_back(new Parent());
    Objects.push_back(new Brother());
    Objects.push_back(new Sister());
    std::cout<<"\n";

    ListObjects<Parent>(Objects);
    ListObjects<Brother>(Objects);
    ListObjects<Sister>(Objects);

    for (Parent* c : Objects)
    {
        delete c;
    }
}

どちらが印刷されますか:

  • 親構築
  • 親構築
  • ブラザー構築
  • 親構築
  • シスター・コンストラクト

  • 兄弟
  • 親が破壊されました

  • ブラザー破壊
  • 親が破壊されました
  • シスター破壊
  • 親が破壊されました

  • プロセスは 0 (0x0) を返しました 実行時間: 0.066 秒

  • 何かキーを押すと続行します。

多くのコメントは、あなたが何を望んでいるのかわからないので、TypeID を使用しないように言っています..しかし、あなたが何を望んでいるかを知っていると仮定すると、「typeid は必要ありません」とはどういう意味ですか? :

#include <iostream>
#include <vector>
#include <typeinfo>

template <class T>
void ListObjects(std::vector<T*> &vec)
{
    for (T* obj : vec)
    {
        //TypeID isn't needed here because the virtual call will figure out which class's << operator to call.

        //If each class has a print function, it can also figure out which class's print function to call..
        //obj->Print(); //works too because each class has a print func.
        std::cout<<*obj<<"\n"; //Works because each class has an overloaded << operator.
    }
}

class Parent
{
    protected:
        virtual void Print(std::ostream& os) const {os<<"Parent\n";}

    public:
        Parent() {std::cout<<"Parent Constructed\n";}
        virtual ~Parent() {std::cout<<"Parent Destructed\n";}

        friend std::ostream& operator << (std::ostream &os, const Parent &p);
};

std::ostream& operator << (std::ostream &os, const Parent &p)
{
    p.Print(os);
    return os;
}

class Brother : public Parent
{
    protected:
        void Print(std::ostream& os) const override {os<<"Brother\n";}

    public:
        Brother(){std::cout<<"Brother Constructed\n";}

        virtual ~Brother() {std::cout<<"Brother Destructed\n";}
};

class Sister : public Parent
{
    protected:
        void Print(std::ostream& os) const override {os<<"Sister\n";}

    public:
        Sister(){std::cout<<"Sister Constructed\n";}
        virtual ~Sister(){std::cout<<"Sister Destructed\n";}
};

int main()
{
    std::vector<Parent*> Objects;
    Objects.push_back(new Parent());
    Objects.push_back(new Brother());
    Objects.push_back(new Sister());
    std::cout<<"\n";

    ListObjects(Objects); //NOTICE we all template types are now inferred.

    for (Parent* c : Objects)
    {
        delete c;
    }
}

上記の呼び出しは仮想であるため、コードは TypeID を使用するコードと同じように出力され、コードではテンプレートの中かっこに何も入力する必要がないことに注意してください。typeid を使用して比較する必要がなくなったため、推論されます。


代わりにテンプレートをパラメーターとして前のコードを要求したため、次のようになります。

template <class T, class U>
void ListObjects(std::vector<U*> &vec)
{
    for (U* obj : vec)
    {
        if (typeid(*obj) == typeid(T))
        {
            obj->Print();
            std::cout<<"\n";
        }
    }
}

次のようになります。

template<typename T>
void ListObjects(std::vector<T*> &vec, const std::type_info &type)
{
    for (T* obj : vec)
    {
        if (typeid(*obj) == type)
        {
            std::cout<<*obj<<"\n";
        }
    }
}

次のように使用します。ListObjects(Objects, typeid(Child));

繰り返しますが、これらはすべてまったく同じ結果になります。それはすべて、ニーズ/ユースケースに依存します。あなたが「何」を達成したいのか、正確にはわかりません。これらはあなたを助けるはずです。

于 2013-10-27T05:09:24.640 に答える
2

コードのどこかで何が起こっているかを把握するためだけにテストの一部としてこれを行っているのでない限り、これは非常に悪い考えであるというコメント者に同意します。

template < typename T >
void listObjects(const std::vector<MyObj*>& vec) {
    for (MyObj* obj: vec) {
        if (typeid(*obj) == typeid(T)) {
            // one of the two below, depending on what your op<< looks like
            std::cout << *obj << std::endl;
            std::cout << dynamic_cast<T&>(*obj) << std::endl;
        }
    }
}

void calledLikeThis(const std::vector<MyObj*>& vec) {
    listObjects<TheseObj>(vec);
}
于 2013-10-27T05:18:57.927 に答える