私はobj-cにかなり精通しており、今はC++をさらに深く掘り下げようとしています。
obj-cの委任パターンに相当するC++を探しています。
プロトコルに準拠する代わりに、クラス(プロトコル)を継承するだけです。小さな例:
class Delegate
{
public:
// Some pure virtual method here.
virtual void method() = 0;
};
class A : Delegate
{
void method() { // Do something here... };
};
class B
{
Delegate your_delegate;
// Somewhere in your code you might need to call the method() using: your_delegate.method();
};
実際には1:1に相当するものはありません。Objective Cは、やや動的に型付けされた言語です。Obj-CのAprotocol
は、特定のシグネチャを持つ関数(「セレクター」)が実行時に存在するという約束のようなものです。実装したくない場合は実装する必要はありませんが、マークが付いていない限り、実行時にクラッシュしたくない場合は実装する必要があります@optional
。
比較すると、C ++は100%静的に型付けされています。何らかの関数が存在する必要があると言う場合、それは存在する必要があります。そうでない場合、プログラムはコンパイルされません。スーパークラスが関数を抽象として宣言する場合、サブクラスはそれを継承する必要があります。多重継承(クラスに複数の分離されたプロトコルを実装させる場合に必要)は地雷原です。
静的型付け(C ++)の利点は、コンパイル時にプログラムが機能的に完全であるかどうか(すべての場所にコードがあるかどうか)を知ることができることです。ただし、これには、Obj-Cのプロトコルと委任を埋めるために他のソリューションを考え出す必要がある場合があります。
「委任」という用語は、依然として適切に適用できます。構文パターンはありませんが、通常のツールを使用してフレームワークでモデル化します。
ここにはたくさんのコードがありますが、インターフェースはかなりきれいです。ユーザーがしなければならないことは、下部にあるほんの少しのコードです。コンストラクターに関連する定型文はまだいくつかありますが、これは将来、C++11の「コンストラクターの継承」構文でなくなる予定です。
/* Class to be used as a member of the delegation host.
Keeps a list of event clients, which you can iterate over.
As a C++11 convenience, function call operator() is overloaded to call
all clients with the given argument list.
This is templated over the base type for the clients. The base type
should define virtual function(s) for handling the events.
Templating is necessary because we can't anticipate the number or types
of these virtual functions. */
template< typename delegate >
struct delegator {
typedef std::list< delegate * > list; // host interface
list delegates;
typedef typename list::iterator delegate_id; // client interface
delegate_id add( delegate *d )
{ return delegates.insert( delegates.end(), d ); }
void remove( delegate_id d )
{ delegates.erase( d ); }
#if __cplusplus >= 201103L // C++11-only convenient host interface
template< typename ... args >
void operator() ( args && ... a ) {
for ( auto d : delegates ) ( *d )( std::forward< args >( a ) ... );
}
#endif
};
/* Abstract base class for all delegate bases. Registers and unregisters
from the delegator, but doesn't define any event handler. */
template< typename derived >
struct delegate {
typedef ::delegator< derived > delegator;
delegator &source;
typename delegator::delegate_id id;
delegate( delegator &in_source )
: source( in_source ),
id( source.add( static_cast< derived * >( this ) ) ) {}
virtual ~delegate() { source.remove( id ); }
};
/* Example delegate base. Defines an event handler which clients must implement.
Other types of events might declare other bases. */
struct my_delegate_base : delegate< my_delegate_base > {
typedef delegate< my_delegate_base > base;
typedef base::delegator delegator;
my_delegate_base( delegator &d ) : base( d ) {}
virtual void operator() ( int ) = 0;
};
/* Example client class defines how to handle an event. */
struct my_delegate_impl : my_delegate_base {
my_delegate_impl( delegator &d ) : my_delegate_base( d ) {}
virtual void operator() ( int i ) {
std::cout << i << '\n';
}
};
実行を参照してください:https ://ideone.com/IRp5rJ