0

これは、C ++コーディング標準で説明されているスイッチオフルールの場合である可能性があり、正しく実行しているかどうか疑問に思っています。スイッチング関数にまだif句があるので疑問に思います。

クラスAが直接インスタンス化されることはありません。常に、BまたはC動的に作成され、への(共有)ポインタを介して均一に処理されAます。であるか。fooであるかに応じて、操作を切り替えて選択します。BC

class A {
public:
  virtual ~A(){}
};

class B : public A {};
class C : public A {};

typedef std::shared_ptr<A> Aptr;
typedef std::shared_ptr<B> Bptr;
typedef std::shared_ptr<C> Cptr;


template<class T>
std::shared_ptr<T> get(const Aptr& pA) {
  return std::dynamic_pointer_cast< T >( pA );
}

void foo( const Bptr& pB ) {
  std::cout << "operate on B\n";
}

void foo( const Cptr& pC ) {
  std::cout << "operate on C\n";
}

void foo( const Aptr& pA ) {
  if ( auto x = get<B>(pA) ) {
    foo(x);
    return;
  }
  if ( auto x = get<C>(pA) ) {
    foo(x);
    return;
  }
  assert(!"oops");
}


int main()
{
  Aptr pA( new C );

  foo( pA );
}

私の質問は、void foo( const Aptr& pA )よりエレガントに実装できるかどうかです。それはなしを意味する可能性がありますif。この状況では、投げ込みgetと巻き込みがfoo推奨されますか?

4

2 に答える 2

2

他の方法で行う正当な理由がない限り(そして、それらがある場合、コードはそれらを表示しません)、これは、仮想関数を介して達成される動的ポリモーフィズムの典型的なユースケースのように思えます。

class A 
{
public:
    virtual ~A() {}
    virtual void foo() = 0;
};

class B : public A 
{
    virtual void foo() 
    {
        std::cout << "operate on B\n";
    }
};

class C : public A 
{
    virtual void foo() 
    {
        std::cout << "operate on B\n";
    }
};

さらに、C ++ 11では、ネイキッドアロケーションを使用std::make_shared<>()したaの構築よりも使用することをお勧めします(特に理由がない限り)。shared_ptrnew

int main()
{
    Aptr pA = std::make_shared<C>();
    pA->foo();
}

仮想関数を使用しない理由があり、別の非侵入型のポリモーフィズムを好む場合は、Boost.Variantをと組み合わせて使用​​できますboost::static_visitorBこれは、関連する必要さえありませんC

#include <boost/variant.hpp>
#include <memory>
#include <iostream>

class B /* ... */ {};
class C /* ... */ {};

// ...
typedef std::shared_ptr<B> Bptr;
typedef std::shared_ptr<C> Cptr;

struct foo_visitor : boost::static_visitor<void>
{
    void operator () (Bptr p)
    {
        std::cout << "operate on B\n";
    }

    void operator () (Cptr p)
    {
        std::cout << "operate on C\n";
    }
};

int main()
{
    boost::variant<Bptr, Cptr> ptr;
    ptr = std::make_shared<C>();

    foo_visitor v;
    ptr.apply_visitor(v);
}

このアプローチは、Boost.Variantが、バリアントが想定する可能性のある各値(この場合はBptrCptr)の処理ケースを含めることを忘れないようにすることを除いて、選択したアプローチと非常によく似ています。

于 2013-03-02T21:54:58.370 に答える
1

仮想メンバー関数を使用するだけです。本物に代わるものはありません

class A {
public:
  virtual ~A(){}
  virtual void foo() = 0;
};

class B : public A {
public:
  virtual void foo() {
     std::cout << "operate on B\n";
  }
};

class C : public A {
public:
  virtual void foo() {
     std::cout << "operate on C\n";
  }
};

そして、良いC++入門書を選んでください。

于 2013-03-02T21:55:41.590 に答える