Objective-Cカテゴリ機能により、プログラマは元のクラス定義で定義されていない新しいメソッドを追加できます。C++のObjective-Cのカテゴリのような構造またはテクニックですか?
C++で同様の機能(言語構成や技術)をアーカイブすることはできますか?
主な関心事は、一貫したメソッド呼び出し構文(.
または->
演算子)です。
Objective-Cカテゴリ機能により、プログラマは元のクラス定義で定義されていない新しいメソッドを追加できます。C++のObjective-Cのカテゴリのような構造またはテクニックですか?
C++で同様の機能(言語構成や技術)をアーカイブすることはできますか?
主な関心事は、一貫したメソッド呼び出し構文(.
または->
演算子)です。
:
struct A {
int x, y;
A(int x, int y) : x(x), y(y) {}
};
ディレクティブ:また、私は次の#importによって生成されたクラスを拡張するために数回をだまし「...プログラムID」を使用しました
このクラスから継承することも、このクラスのインスタンスを含むラッパークラスを作成することもできます。ほとんどの場合、継承はそれがにインスタンスA
を促進し、(含まれている)C++ 11件の移動セマンティクスを持つA.
ををラップラッパークラスがAではないとして、移動するための方法ですが、 (A
を継承)サブクラスB
が効率的になり、インスタンスA
をコピーする必要はありません。例と
class B : public A {
public:
B (A &&a) : A(a), someOtherMember(a.x + a.y) {}
// added public stuff:
int someOtherFunction() const { return someOtherMember; }
private:
// added private stuff:
int someOtherMember;
};
全コード:もちろんhttp://ideone.com/mZLLEu
私は追加機能元のメンバーx
とy
のそれ以上の変更を尊重しないため、少しばかげています(でもメンバーはもっと似ています)が、私は何を実証したいのか分かります。
コンストラクタB (A &&a)
は、私が "コンストラクタを昇格する"(これは標準的な用語ではありません)と呼ばれるものです。通常、B (B &&b)
は移動コンストラクタであり、 B
インスタンスの内容を新しい約B
に移動します。は、です。私は移動意味をに、のインスタンスをA
(別の関数によって返されたもの)に、にA
のB
に移動します。
A
をB
をA
として使用できるようにしながら、効果的にA
をB
に昇格できます。
ソートの回答とは対照的に、私のソリューションは、安全でないポインタキャストに頼っていないため、仮想テーブルを追加しても機能します。
私はctor *を移動すると意味的に新しいオブジェクトが作成され、コンパイラは可能であれば既存のオブジェクトを再利用できることを理解しました。また、あなたの* ctor *の宣伝もコンパイラ最適化のための同じチャンスを持っています。私の理解は正しいのですか? – Eonil
'A(A && a)'は 'A'の移動先です。古いAを新しいAに移動します。意味的には新しいオブジェクトですが、セマンティクスを動かすことで古いAの内容を "盗む"ことができます。私のアプローチの考え方は古いAをBに変えることです。 'B'は' A'から継承しているので、 'A'を初期化しなければなりません。私は「B」の一部のコンストラクタで「A」の移動を使用します。これは、コンテンツに触れることなく、既存の「A」から「B」に効果的に昇格させるためです。その移動体がよく書かれている限り、「A」のもの)。 – leemes
ここには繊細さがあります。 'クラスC:パブリックA'、' A'からの移動コンストラクタ。その場合、オブジェクトは 'A'、' B'、または 'C'です。同時に「B」と「C」の両方になることはできません。 – alastair
C++には継承があります。のは、以下のクラスを拡張する考えてみましょう
// This one is part of external framework, or auto-generated, or dllimport, or #import, etc..
class A
{
protected double m_x;
};
// This one is the extension class. Make sure you only add non-virtual methods here.
// Static methods and static data members are OK as well.
class __declspec(novtable) B: public A
{
public:
double getSquare(){ return m_x * m_x; }
__declspec(property(get = getSquare)) double square;
};
// Usage example
double someFunc(A& arg)
{
B& b = static_cast<B&>(arg); // Note we've not constructed any instance of B, just casted.
return b.square;
}
実際、私はちょうど同じような(多分同じ?)技術を考え出し、新しい[question]を投稿しました(http://stackoverflow.com/questions/14952504/is-it-possible-to-cast-an-object-to -a-subclass-does-not-defined-extra-v)を使用します。この技術は標準的に安全ですか? – Eonil
'__declspec'と' property'はISO標準C++の一部ではありません。 –
私はそれがVisual Studio 2005と2008でうまくいっていると確信しています。私はそれが標準であるのか分かりませんし、正直言って私は気にしません。 "Standard C++"は、もう一つの漏れやすい抽象化です。あなたのC++コードがコンパイラA、B、Cでビルドされていることを確認するには、そのように開発してテストする必要があります。 – Soonts
いくつかでは「クリーン」ではないかもしれませんが(私の意見ではありますが)同じことを達成する別のオプションは、静的クラスを使用しています。メンバー関数を作成するときに実際に何が起こっているのかということは、コンパイルがオブジェクト(別名「this」)が最初のパラメータである関数を生成するということです。だから、同じことをしてクラスの機能を継承せずに拡張することもできます。
class Something
{
public:
Something()
~Something()
}
// In objective-c you may call this category Something+Utils
class SomethingUtils
{
// You can use a pointer, or a reference here, your call.
static int GetSomethingElse(Something *something, int parameter);
}
これは、カテゴリと同じ意図を達成します:あなたは、あなたのクラスオブジェクトの機能を拡張し、新しい派生クラスを作成する必要はありません。プライベートメンバーや保護されたメンバーの関数や変数にアクセスすることはできませんが、とにかくそれを行うことはできません。カテゴリのポイントを完全に見逃してしまった)。あなたは、あなたを使用することはできません。と - >演算子が、私の意見では、いくつかのユーティリティメソッドを追加するだけで新しい型を派生するよりもはるかに優れた妥協点です。
これは構文的に醜いですが、私はこれが最も実用的な選択肢であることに同意する必要があります。 @leemesの解決策でさえ、私はこのようなユーティリティクラスをいくつか書いて、それをまとめます。 – Eonil
いくつかの点で文体的に魅力的なやや変化しているのは、代わりに名前空間を使用することです。 –
私はEonilを追加します。あなたが構文的に醜い(私は個人的にそうではない)と見なすことができますが、それは構文的にはっきりしています。これは、コアメソッドではなく、クラス拡張であることが暗黙のうちに明らかです。obj-cカテゴリの問題(ヘッダファイルにメソッドを従わせることで、それがカテゴリであることを理解する必要があります)。醜さについては、私は決してその目で目を見ないので、私はそれを議論しません:) –
私は1年ほど前、an idea I talked about in a lightning talkとほぼ一貫した呼び出し規約を得た:
(イントロは彼の論評なしであまり意味があります - それはC++ビットになるゴマ待ちます)。材料は真剣に取られることを意図していなかったことを
注 - クラス定義へのアクセスを持っている場合、一部がは、必然的に、はい;-)
を持っています。そうでない場合は、 –
実行時には、言語サポートはありません。しかし、あなたはそれを行うことができます。関数ポインタを含むマップしかし、それはむしろ扱いにくく、エラーを起こしやすい。 –
@AlokSaveあなたはソースコードを直接変更することはできますか?それはオプションかもしれない。 – Eonil