6

C++ では、関数の引数を複数の型に定義することは可能ですか?

#include <iostream>
using namespace std;

class A {
public:
   void  PrintA() { cout << "A" << endl;}
};

class B {
public:
   void  PrintB() { cout << "B" << endl;}
};

class C: public A, public B {
public:
   C(){;}
};

class D: public A, public B {
public:
   D(){;}
};

///
void __printall__(A*a, B*b){
   a->PrintA();
   b->PrintB();
}
#define printall(a) __printall__(a,a)
///

int main(int argc, char *argv[]){
   C c;
   D d;
   printall(&c);
   printall(&d);
}

コメント間のコードをマクロを使用していないものに変更したい。型の安全性を維持したいので、ポインターのキャストを強制しません。C/D と A/B の間に別のクラスを導入することさえしません。実際には、私のクラス階層はコードに示されているものよりも少し複雑であり、A または B から派生したすべてのクラスをリベースすることは望ましくないからです。

4

3 に答える 3

4

@Torstenがアドバイスしたように、考えられる解決策は、関数テンプレートを使用して、任意のタイプの引数を渡すことができるようにすることです。ただし、単純なテンプレートは、適切なメンバー(この場合はprintAおよびprintB)を提供する任意のタイプで機能するため、次の関数テンプレート

template <typename T>
void printAll(T const & t)
{
    t.printA();
    t.printB();
}

次のタイプで動作します

struct Foo
{
    void printA() const { std::cout << "FooA\n"; }
    void printB() const { std::cout << "FooB\n"; }
}

printAll(Foo());

またはFooから派生していなくても。これは望ましいことかもしれませんが、引数がaとaでなければならないという事実を本当に強制したい場合は、関数で静的アサーションを使用して次のことを確認できます。ABAB

#include <type_traits>

template <typename T>
void printAll(T const & t)
{
    static_assert(std::is_base_of<A, T>::value && std::is_base_of<B, T>::value,
                  "T must be derived from A and B");

    t.printA();
    t.printB();
} 

別の解決策は、テンプレートパラメータが実際にとの派生クラスである場合にのみ関数テンプレートを定義するために使用することstd::enable_ifです。AB

template<
    typename T ,
    typename = typename std::enable_if<
        std::is_base_of<A, T>::value &&
        std::is_base_of<B, T>::value
    >::type
>
void printAll(T const & t)
{
    t.printA();
    t.printB();
}

注意static_assertenable_ifおよびis_base_ofはC++11の機能です。C ++ 03を使用している場合は、さまざまなBoostライブラリで同等のものを見つけることができます。

于 2012-07-18T11:53:17.997 に答える
3

テンプレート バージョンは、関数に渡される型を選択するだけです。

template < class T >
void printall( T* t )
{
   t->printA();
   t->printB();
}
于 2012-07-18T10:57:37.513 に答える
1

トルステンは正しい。代わりに、実行時に「遅延バインディング」のようなものを探している場合は、関数ポインターを使用できます。ここで明確な例を見つけることができます。

于 2012-07-18T11:01:15.800 に答える