1

両方がによってのみ作成できる2つのクラスを取りますnew。1つのクラスはベースで、もう1つのクラスは派生です。派生クラスはメソッドを追加するだけです。

class Base
{};

class Derived : public Base
{};

Base * b = new Base{}
Derived * d = covert( b );

// - or -

Base * b = new Base{};
convert( b ); // converts Base to Derived
Derived * d = dynamic_cast<Derived *>(b);

私がやりたいのは、Base割り当てられたクラスデータを取得し、何らかのメソッドまたは関数を介して導関数で拡張/ラップすることconvertです。

更新: 組み込みシステムのメモリを構築することはほとんどないので、メモリ割り当ての量を減らすためにできる限りのことをしています。すでに割り当てられている基本クラスを拡張して、派生物でラップする方法があるのではないかと思っていました。

その他の更新: 組み込みシステムはARMであり、現在LLVMコンパイラを使用していますが、これは将来的には当てはまらない可能性があります。したがって、標準に準拠した方法が推奨されます。

4

7 に答える 7

2

C++ではクラスのプロモートはできません。あなたがしたいと思うかもしれないことは-あなたが言ったように-ラップBaseインすることですDerived

class BaseInterface { ... };

class DerivedInterface: public BaseInterface { ... };

class Base: public BaseInterface { ... };

class Derived: public DerivedInterface {
private:
  Base* base;
public:
  Derived(Base* useBase): base(useBase) {}
  ~Derived() { delete base; }
  // implement using base
};

そしてそれをそのように使用します:

Base* object = new Base(...);
// use object with base functionality
object = new Derived(object);
// use object with derived functionality
delete object; // free both base and derived memory
于 2012-10-19T11:47:14.900 に答える
2

私があなたの質問を正しく理解している場合、考えられる解決策の1つは、継承の代わりに集計を使用することです。

class Base
{/*has only the data*/}

class Derived 
{
    Base &base;
    Derived(Base &b) : base(b) {}
    //now methods from derived will use the data members from instance passed in constructor
    //if is possible the Derived needs to be a friend class of Base in case there are no getter for all members
}

参照の代わりに、必要に応じてスマートポインタを使用できます。このようにして、Baseオブジェクトからのデータを使用する新しいDerivedオブジェクトを作成することにより、キャストを回避します。

于 2012-10-19T11:54:08.257 に答える
1

派生クラスはメソッドを追加するだけです。

それでは、そのクラスの意味はありません。まったく。

派生を使用して、次のことを行うことができます。

  • メソッドをオーバーライドvirtualする(したがって、動作をカスタマイズする)=>良い
  • 基本クラスのデータを拡張する => 悪い、コードの再利用には構成を使用する必要がありますが、それでも機能します

あなたの特定のケースでは?それはただ役に立たない。それはテーブルに何ももたらしません。基本クラスに新しい機能を追加したい場合は、無料の関数を実装してください。おまけとして、派生クラスを取り除くことで、キャストする必要もなくなります。

于 2012-10-19T13:17:31.940 に答える
1

C++11 のおかげで可能性のある選択肢が生まれる

class Base
{
  pubilc:
    Data data;

    Base( Base && base ) : data( std::move( base.data ) ) {} 
};

class Derived : public Base
{
  pubilc:
    static Derived * convert( Base *& base )
    {
        Derived * d = new Derived{ std::move( *base ) };
        delete base;

        base = d;
        return d;
    }
 };

記憶的には望んだものではありませんが、私の知る限り、小さなヒットに過ぎません。Derivedmove コンストラクトを使用すると、古いオブジェクトを削除する前に新しいオブジェクトを作成するだけのオーバーヘッドが発生しBaseます。

何かを行う前にチェックが必要ですが、今のところはこれで十分です。

于 2012-10-19T14:51:30.183 に答える
0
Derived *d =static_cast<Derived *>(b); //? :-/

ここに1つの説明があります

別の説明

内部で何が起こっているかについてのより詳細な説明

アップデート:

StackOverflow-c++でstatic_castを使用したダウンキャスト

static_castを使用したC++でのダウンキャスト

仕様:

タイプ「pointertocv1B」(Bはクラスタイプ)の右辺値は、タイプ「pointer to cv2 D」の右辺値に変換できます。ここで、Dは、有効な標準の場合、Bから派生したクラス(10節)です。 「ポインターからD」から「ポインターからB」への変換が存在し(4.10)、cv2はcv1と同じかそれ以上のcvqualificationであり、BはDの仮想基本クラスではありません。nullポインター値(4.10)宛先タイプのnullポインタ値に変換されます。タイプ「pointertocv1B」の右辺値が、実際にはタイプDのオブジェクトのサブオブジェクトであるBを指している場合、結果のポインターはタイプDの囲んでいるオブジェクトを指します。それ以外の場合、キャストの結果は未定義です。

LLVMの場合のみ:

http://llvm.org/docs/HowToSetUpLLVMStyleRTTI.html-ダウンキャスティングを許可します(C ++ RTTIを使用しないため、未定義の動作ではありません)。

標準に準拠したダウンキャストの方法はありません。

class Parent{
    public: void gotoWork(){ cout << doWork(); }
};

class Child: public Parent{
     public: void gotoSchool(){ cout << attendClasses();}
};

Parent *p = new Parent();
Child *ch = static_cast<Child*> p;
//now child has to go work? :-(

編集

他のすべての方法とは別に、2つのオブジェクトを配置してみませんか?タイプ「ベース」とタイプ「派生」の1つをUNIONに入れますか?

PS:その言語仕様に準拠しています。

于 2012-10-19T11:59:40.437 に答える
0

私が持っている多くの答えを見ると、共通のコンセンサスは、私が言ったことを実行し、実際にBaseクラス内でDerivedクラスをラップする必要があるということです。私がこれをしなかった理由は、継承で得られる特定の動作を失うからです。この動作は、Derivedクラスのポインターをタイプのポインターに設定します。これは、クラスをクラスに変換Baseする何らかの変換を行った後に発生します。BaseDerived

Aは、私自身の解決策につまずきました-明らかにコンパイルされないかもしれませんが-そして他の多くの良いアイデアもありました。結局、私の場合、私のDerivedクラスは仮想メソッドをオーバーライドしないため、継承を使用する利点がないことに気付くのに少し時間がかかりました。最善の方法は、実際にコンポジションを使用することです。

class Base
{
    // some nice implementation
};

class Derived
{
  public:
    Derived( Base && base )
    {
        this->_base = base;
    }

    Base & base()
    {
        return _base;
    }

  private:
    Base _base;
};
于 2012-10-20T09:44:52.773 に答える
0

基本クラスのフレンドであるヘルパー クラスを追加し、それに追加の機能を追加することができます。

class Base 
{
   friend class BaseHelper;
   // ....
};
class BaseHelper
{
    public:
    // all functions can access data into Base objects:
    void f(const Base& b) const; // can only read data in b, not change it
    void g(Base& b); // can change data in b
}
于 2012-10-19T11:40:18.357 に答える