3

私はC++でこれを行うことに興味がありました:

ユーザーに配布する小さなライブラリがあるとしましょう。クライアントに、必要なバイナリファイルと関連するヘッダーファイルの両方を提供します。たとえば、次のヘッダーが開発で使用されていると仮定します。

#include <string>

ClassA 
{
    public:
        bool setString(const std::string & str);

    private:
        std::string str;
};

さて、私の質問です。展開に関して、クライアントに「reduced」ヘッダーを与えることに根本的な問題はありますか?たとえば、プライベートセクションを削除して、次のように指定できますか。

#include <string>

ClassA 
{
    public:
        bool setString(const std::string & str);
};

私の本能は「はい、これは可能ですが、落とし穴があります」と言っているので、ここでこの質問をしているのです。これが可能で安全であれば、プライベート変数を非表示にするための優れた方法のように見えます。したがって、場合によっては前方宣言を回避することもできます。

シンボルはまだバイナリ自体に存在し、これはソースコードレベルでの可視性にすぎないことを認識しています。

ありがとう!

4

3 に答える 3

6

この方法でクラス宣言を変更すると、互換性のないコードが発生します。

コンパイラは、そのクラスのインスタンスが占めるスペースの量と、そのスペースのどこにメンバー変数が配置されているかを把握するためにクラス宣言を必要とします。

1 つのヘッダーでメンバー (プライベート メンバーであっても) を除外すると、このヘッダーでコンパイルされたコードはクラスの別のレイアウトを想定します。クラスのインスタンスに割り当てられるスペースが少なくなり、メンバー変数が不適切な場所にあると見なされます。

于 2012-11-30T17:08:59.310 に答える
2

Qt(クロスプラットフォームC ++ライブラリのセット)は、プライベートヘッダーと「d」ポインターを使用して実装の詳細を非表示にする手法を使用します。バイナリ互換性のあるライブラリを長期間維持するのはかなり巧妙だと思いますが、必要に応じて実装を変更することができます。

http://zchydem.enume.net/2010/01/19/qt-howto-private-classes-and-d-pointers/

于 2012-11-30T17:26:28.407 に答える
2

sthが彼の回答で言ったことに加えて、このようなことをする理由がある場合は、ClassAを純粋仮想関数のみを持つ「インターフェイス」型クラスにしてみませんか。

内部コードには、ClassAから派生し、これらすべての純粋仮想関数を実装するClassBが含まれます。ClassAのヘッダーのみを配布します。ClassAは純粋な仮想クラスであり、ClassBについて何も知らないため、スタックまたはヒープ上にClassBオブジェクトを直接作成できないため、明らかにユーザーはスタック上でClassAオブジェクトを宣言できません。

パブリックヘッダーファイル(これをユーザーに配布します):

class A 
{
public:
   virtual ~A()
   { // necessary - don't remove.
   }

   virtual somefunc() = 0;
   virtual someotherfunc(int a, int b) = 0;
   virtual bool setString(const std::string & str) = 0;
};

// This function creates an instance of object B. You must
// call delete on the returned pointer when you're done with it!
A *CreateObjectB();

プライベートヘッダーファイル:

class B : public class A
{
private:
    ...

public:
   B();
   virtual ~B();

   virtual somefunc();
   virtual someotherfunc(int a, int b);
   virtual bool setString(const std::string & str);
};

プライベートソースファイル:

classB::B()
{

}

classB::~B()
{

}

classB::somefunc()
{
    ...
}

classB::someotherfunc(int a, int b)
{
    ...
}

classB::setString(const std::string & str)
{
    ...
}

A *CreateObjectB()
{
    return new B();
}
于 2012-11-30T17:26:46.093 に答える