2016-07-22 9 views
2

Object slicingの奇妙なケースがあります。私は私のベースと派生クラスの両方がシングルトンなので、シングルトンクラスが必要なプロジェクトに取り組んでいます。以下のサンプルケースは私の状況を説明しています。C++の奇妙なケースBase class静的参照データメンバのオブジェクトのスライシング動作

は、これが私の基本クラスです

// Base.h 
class Base 
{ 
    public: 

     static Base& base; 

     virtual void doSomething(){ cout<<"Base Do Something"<<endl; } 

    protected: 

     Base(); 
     virtual ~Base(); 
     static Base& getBaseInstance(); 

    private: 
}; 

//Base.cpp 
Base::Base() 
{ 
    //ctor 
} 

Base::~Base() 
{ 
    //dtor 
} 

Base& Base::getBaseInstance() 
{ 
    static Base object; 
    return object; 
} 
Base& Base::base=Base::getBaseInstance(); 

これは私の派生クラス

class Derived: public Base 
{ 
    public: 

    static Derived& derived; 
    virtual void doSomething(){ cout<<"Derive Do Something"<<endl; } 

    static Derived& getDerivedInstance(); 
    protected: 
     Derived(); 
     virtual ~Derived(); 

    private: 
}; 

Derived::Derived() 
{ 
    //ctor 
} 

Derived::~Derived() 
{ 
    //dtor 
} 

Derived& Derived::derived=Derived::getDerivedInstance(); 

Derived& Derived::getDerivedInstance() 
{ 
    static Derived object; 
    return object; 
} 

され、最終的にこれが私の主な機能

int main() 
{ 
    cout << "Hello world!" << endl; 
    Base::base.doSomething(); 
    Derived::derived.doSomething(); 

    Base::base=Derived::derived; 

    Base::base.doSomething(); 

    Base::base=Derived::getDerivedInstance(); 

    Base::base.doSomething(); 

    Base& r = Derived::derived; 

    r.doSomething(); 

    Base::base=Derived::getDerivedInstance(); 
    Base::base.doSomething(); 
    return 0; 
} 

であり、私はこのために、次の出力を取得しています

Hello world! 
Base Do Something 
Derive Do Something 
Base Do Something 
Base Do Something 
Derive Do Something 
Base Do Something 

私の質問はオブジェクトのスライスが参照上で機能しないはずだから、なぜ私は上書きすることができないのですか?Base::base参照派生オブジェクトの基本クラスの静的データメンバーとして作成しましたか?これはうまくいくのですがBase& r = Derived::derived;

r.doSomething()で何かを呼び出すと、私は派生クラスのdoSomethingを取得します。しかし、これは

Base::base=Derived::derived;  
    Base::base.doSomething(); 

または

Base::base=Derived::getDerivedInstance();  
    Base::base.doSomething(); 

となる明確化の任意の並べ替えではありません理解されるであろう。 ありがとうございます。

+0

参照を辞退することはできません。あなたのように見えたら、何が起こっているのかスライシングです。 –

+0

ありがとうございます。私はそのようなばかげたミスを犯した(コーディング2泊まっすぐ、私はちょうど眠るべきだと思う)もう一度ありがとう。 –

答えて

3

あなたは

Base::base=Derived::derived; 

を行うとあなたが派生クラスを参照するためにベース基準を設定していません。これは代入演算子で、Baseの部分はderivedbaseの部分のみです。

baseはタイプBaseのままですと、参照がしか一度初期化することができ、あなたは、この再割り当て動作が必要な場合は

Base& Base::base=Base::getBaseInstance(); 

であなたはポインタ型を使用する必要があるとしていることを行うよう変更することはできません。

+0

Ohhh私は、参照が一度しか初期化できないという事実を完全に忘れていました。再度、感謝します。 –

+1

@ Dr.Xperience問題ありません。喜んで助けてください。 – NathanOliver

1

参照は、すべての目的のために参照されるオブジェクトです。参照に割り当てることは、参照されるオブジェクトに割り当てることです。あなたの場合、オブジェクトにはデータメンバーがないので、効果はありません。

特に検出可能なスライシングはありません。

宣言

Base& r = Derived::derived; 

&hellip。非常に異なるケースです:初期化であり、割り当てではありません。

初期化では、参照が指定されたオブジェクトを参照します。

その後、参照は変更できません。


他のニュースでは:

  • グローバル(参照)は、静的初期化の順序の大失敗のリスクを実行します。それらは、シングルトンゲッター関数の利点を無効にするためだけに役立ちます。グローバルでは、関数はまさに無駄な追加の冗長性です。

  • データメンバを持つ変更可能なシングルトンは、コードの広く離れた部分と見かけ上接続されていない部分の間の通信を可能にします。これにより、現在の状態や何が何に影響を与えるかについての前提に頼ることが難しくなります。そのため、グローバル変数はすべてのプログラミング言語でEvil ™とみなされるため、シングルトンは慎重に使用してください。

+0

これは単なるサンプルです。私の実際のケースではDerivedクラスに多くのメンバーがいます。手伝ってくれてありがとう。私はそんなに愚かな間違いをした。 –

+0

私のプロジェクトは2つのシングルトンしか持っていません。彼らはサービスプロバイダとして行動します。ドライバサービスプロバイダにとっては、かなりオーバーヘッドです。 –

1

Base::baseはスタティックリファレンスです。それをここにintialize:

Base& Base::base=Base::getBaseInstance(); 

この時点から以降(つまり、あなたのコードの前baseを使用して実行される)、baseはベースインスタンス(Base::getBaseInstance()で宣言された、すなわち静的インスタンス)を指します。

これを実行すると、参照はもう変更されませんが、baseで参照されるオブジェクトにオブジェクトをコピーします(ベースタイプなので、スライスします)。

回避策は、Base :: baseをポインタにすることです。このようにして、それを変更して派生オブジェクトを指すことができます。しかし、これはシングルトンのアプローチに適しています(基本オブジェクトはどこかにあり、派生オブジェクトを持つためです)。

+0

"それゆえスライシング"、データメンバーが存在しないので、検出可能なスライシングは不可能です。 –

+0

ありがとう、私はポインタのアプローチについて知っています。最低限のトレース数(インテルトレース/プリデコード)を避けるだけです。再度、感謝します。 –

+0

@ Cheersandhth.-Alfにはデータメンバーはいませんが、仮想関数があります。代入は単純なオブジェクトについてのものであるため、Derivedタイプは失われるため、期待される仮想関数をこれ以上使用しません。私はnatike英語のスピーカーではない:私はいくつかの情報が失われると、[この定義を使用して "スライス"(http://stackoverflow.com/questions/274626/what-is-object-slicing)を使用しますが、あなたかもしれないより良い言葉を提案することができます。 – Christophe

関連する問題