0

ポリモーフィック オブジェクト メンバーに関する私の質問に対して、昨日エレガントな回答を得ました。

しかし今、変数が期待どおりに動作していないという問題に直面しています。次のコードが使用されています。

#include <iostream>
#include <math.h>

using std::cin;
using std::cout;
using std::endl;


class Com
{
    public:
        virtual void setReady()
        {
            cout << "Com" << endl;
        }
};

class DerivedCom : public Com
{
    public:
        void setReady()
        {
            cout << "DCom" << endl;
        }

        void somethingElse()
        {
            cout << "else" << endl;
        }

};

class BaseClass
{
    public:
        Com* com;

    public:
        BaseClass(Com* c = new Com) : com(c)
        {
        }

        virtual void setReady()
        {
            com->setReady();
        }
};

class DerivedClass : public BaseClass
{
    // the call to somethingElse() won't compile if I leave out this declaration
    protected:
        DerivedCom* com;

    public:
        DerivedClass() : BaseClass(new DerivedCom) 
        {
        }

        void setReady()
        {
            // This line causes a segfault if I put in the declaration earlier
            this->com->setReady();

            // This line won't compile if I leave out the declaration earlier
            this->com->somethingElse();
        }
};

int main()
{
    DerivedClass* inst = new DerivedClass();

    inst->setReady();
    return 0;
}

問題は、それDerivedClass::comは実際にはタイプですが、コンパイラがそれらを見つけられないため、特定のメソッドにDerivedComアクセスできないことです。DerivedCom追加の re-declaration を入れるとDerivedCom* com、コンパイラはメソッドを見つけますが、セグメンテーション エラーが発生します。

4

2 に答える 2

3

その余分な宣言を削除します。

a が a であると確信している場合Com*は、DerivedCom*それが可能static_castです。

static_cast<DerivedCom*>(this->com)->somethingElse();

ただし、これは間違っているとクラッシュする可能性があります。あなたが確信が持てないなら、あなたはそれをすることができdynamic_castます

DerivedCom* dcom = dynamic_cast<DerivedCom*>(this->com);
if (dcom)
    dcom->somethingElse();

dynamic_castオブジェクトが要求したタイプでない場合は NULL を返します。

于 2012-11-20T13:48:22.663 に答える
0

セグメンテーション違反の理由は、変数を別の型で再度宣言していないためです。実際には、派生クラスで初期化されていない新しいポインターを定義しています。したがって、初期化されていないポインターthis->com->...であるため、派生クラスにアクセスしてcomクラッシュします。

あなたがやろうとしているのは、メンバーポインタの型を変更することです。次のように、メンバー ポインターの型をテンプレート変数として作成することで、これを行うことができます。

template <class ComType>
class BaseClassTemplate
{
    ComType* com;
    ...;
};

typedef BaseClassTemplate<Com> BaseClass;

class DerivedClass : public BaseClassTemplate<DerivedCom>
{
    ...;
};

ただし、これにより基本クラスがテンプレートになるため、必要に応じて取得するには、インスタンス化しBaseClass<Com>て基本クラスのバージョンを取得する必要があります。私が示したように、派生クラスにするか、単なるtypedefにすることができます。

于 2012-11-20T14:06:48.107 に答える