42

C++ で、クラスが記述されている元のソース ファイルを編集せずに、別のソース ファイルでクラスを拡張する (メソッドを追加する) ことは可能ですか?

obj-c では、別のものを書くことで可能です@interface AbcClass (ExtCategory) ... @end

次のようなことをしようとすると、コンパイル時エラーが発生しました。

//Abc.h
class Abc {            //This class is from a 3rd party library....
                       //  ...I don't want to edit its source file.
    void methodOne();
    void methodTwo();

}


//Abc+Ext.h
class Abc {       // ERROR: Redefinition of 'Abc'
    void methodAdded();
}

私の目標は、「Abc」名を保持し、それにメソッドを追加することです。私が使用したサードパーティ ライブラリの特定のクラスにはいくつかのメソッドがありません。これらのメソッドを追加したいのですが、ソース ファイルを編集せずに残しています。

これを行う方法はありますか?私は C++ コードを書くのが初めてです。私はその構文のいくつかに精通していますが、あまり知りません。

4

5 に答える 5

37

いいえ。この種のクラス拡張は では不可能ですC++。ただし、元のソース ファイルからクラスを継承し、ソース ファイルに新しい関数を追加することはできます。

//Abc.h
class Abc {
    void methodOne();
    void methodTwo();
};


//Abc+Ext.h
class AbcExt : public Abc {       
    void methodAdded();
};

その後、次のようにメソッドを呼び出すことができます。

std::unique_ptr<AbcExt> obj = std::make_unique<AbcExt>();
obj->methodOne(); // by the virtue of base class
obj->methodAdded(); // by the virtue of derived class
于 2013-09-14T17:26:37.317 に答える
2

現在の C++ でこれを直接行うための特定のメカニズムはありませんが、定型的な作業を犠牲にして同様のことを実現する方法がいくつかあります。

方法 1:

// foo.h
class Foo {
private:      // stuff
public:       // stuff

private:
    // All this crap is private. Pretend like I didn't expose it.
    // yeah, I know, you have to compile it, and it probably adds
    // dependencies you don't want to #include, like <string>
    // or boost, but suck it up, cupcake. Stroustrup hates life.
    void internalHelper(std::string&, std::vector&, boost::everything&);
};

方法 2:

// foo.h
class Foo {
private:      // stuff
public:       // stuff
};

// fooimpl.h
// Internal file, do not export with the API.
class FooImpl : public Foo {
private:      // stuff
public:       // stuff
    // So yeah, you have to go thru a cast and an extra include
    // if you want to access this. Suck it up, cupcake.
    void internalHelper(std::string&, std::vector&, boost::everything&);
};

方法 3:

// foo.h
class Foo {
private:      // stuff
public:       // stuff

    // For the private api: this is the worst approach, since it
    // exposes stuff and forces include/cruft on consumers.
    friend void foo_internalHelper(std::string&, std::vector&, boost::everything&);
};

// foo.cpp

// don't make it static or anyone can make their own as a way to
// back door into our class.
void foo_internalHelper(...);

方法 4:

// foo.h
class Foo {
private:      // stuff
public:       // stuff

    // No dependencies, but nothing stops an end-user from creating
    // a FooPrivate themselves...
    friend class FooPrivate;
};

// foo1.cpp
class FooPrivate {
public:
    void fooInternalHelper(Foo* f) {
       f->m_privateInternalYouCantSeeMe = "Oh, but I can";
    }
};
于 2013-09-14T18:09:31.640 に答える