2

IHandler純粋な抽象クラスとそれから派生したクラスがあるとしましょう:

class IHandler
{
public:
   virtual int process_input(char input) = 0;
};

class MyEngine : protected IHandler
{
public:
   virtual int process_input(char input) { /* implementation */ } 
};

MyEngine でそのクラスを継承して、MyEngine*期待しているすべての人に渡してIHandler*、それらを使用できるようにしたいと考えていますprocess_input。ただし、MyEngine*実装の詳細を公開したくないため、アクセスを許可したくありません。

MyEngine* ptr = new MyEngine();
ptr->process_input('a');                           //NOT POSSIBLE
static_cast<IHandler*>(ptr)->process_input('a');   //OK
IHandler* ptr2 = ptr;                              //OK
ptr2->process_input('a');                          //OK

これは、保護された継承と暗黙のキャストを介して行うことができますか? 私はなんとか得ることができました:

「MyEngine *」から「IHandler *」への変換は存在しますが、アクセスできません

私は C# のバックグラウンドを持っているので、これは基本的に C# での明示的なインターフェイスの実装です。これは C++ で有効なアプローチですか?

追加:

なぜこれをやりたいのかをよりよく理解するために、次のことを検討してください。

クラスTcpConnectionは TCP を介した通信を実装し、そのコンストラクターには interface へのポインターが必要ITcpEventHandlerです。ソケットでデータを取得するTcpConnectionと、そのデータをITcpEventHandlerusingに渡します。ITcpEventHandler::incomingDataまたは、送信データをポーリングするときに、 uses を渡しますITcpEventHandler::getOutgoingData

私のクラスHttpClientTcpConnection(集約)を使用してTcpConnectionコンストラクターに渡し、それらのインターフェースメソッドで処理を行います。

したがって、これらのメソッドを実装する必要がありますが、使用しているユーザーがメソッド ( 、 )に直接アクセスできるようにしTcpConnectionたくありません。電話をかけたり、直接電話したりできないようにする必要があります。HttpClientITcpEventHandlerincomingDatagetOutgoingDataincomingDatagetOutgoingData

これが私のユースケースを明確にすることを願っています。

4

3 に答える 3

6

で派生するとprotected、派生クラスへのポインターを介して基本クラスのメンバーにアクセスできなくなり、暗黙的な変換が許可されなくなります。

あなたが望むのは、基本クラス(インターフェース)を介したアクセスを禁止することではなく、派生クラス(具体的な実装)を介したアクセスを禁止することだと私には思えます:

class IHandler
{
public:
   virtual int process_input(char input) = 0;         //pure virtual
   virtual std::string name() { return "IHandler"; }  //simple implementation
};

class MyEngine : public IHandler
//               ^^^^^^
{
protected: // <== Make the functions inaccessible from a pointer
           //     or reference to `MyEngine`.

   virtual int process_input(char input) { return 0; }   //override pure virtual
   using IHandler::name;                                 //use IHandler version
};

ここで、派生クラスでは、基本的にprocess_input関数の可視性をオーバーライドするため、クライアントは基本クラスへのポインターまたは参照を介してのみ呼び出すことができます。

このようにして、これを不可能にします:

MyEngine* ptr = new MyEngine();
ptr->process_input('a');   // ERROR!
std::cout << ptr->name();  // ERROR!

しかし、これは可能になります:

IHandler* ptr = new MyEngine();
ptr->process_input('a');   // OK
std::cout << ptr->name();  // OK
于 2013-03-22T13:09:02.407 に答える
1

C++ ではprotected、継承は実装privateの継承の使用に役立ちます。つまり、メソッドを使用してクラス、たとえばテンプレートクラスを定義し、その機能を使用したいがインターフェースを使用したくない場合は、またはを継承します。したがって、実際には、サブクラスで使用するメソッドを基本クラスで定義する必要があります。protectedprivate

このトピックに関するリンクはこちらです。それは本当に難しいです、私は同意します。

于 2013-03-22T13:08:10.043 に答える