0

2種類のクラスを作りたいです。クラスには同様の関数「set」がありますが、set 関数はクラス B で「int」を取得し、クラス C で double を取得します (A は抽象 calss ですが、必要ありません)。私は何をする必要がありますか?

class A{
    int x;
public:
    A (int t=1): x(t){}
    virtual void set ()=0;
}

class B: public A{
    int y;
public:
    virtual void set (int y);
};

class C: public A{
    double y;
public:
    virtual void set (double y);
};

void main ()
{
    B b; //error
    C c; //error
}
4

4 に答える 4

2

単一のテンプレートクラスを作成し、その時点で必要なものをインスタンス化するか、テンプレートクラスからBとCをtypedefします。

template< typename T > class A
{
public:             A() : mValue() {}

            void    Set( T value ) { mValue = value; }

private:    T       mValue;
};

typedef A< int >    B;
typedef A< double > C;
于 2013-02-24T19:46:30.443 に答える
1

これを解決するにはかなり多くのバリエーションがありますが、まず第一に、仮想関数には同じ署名が必要です (例外がある可能性がありますが、それはあなたのケースには関係ありません)。したがって、解決策は、すべてのケースを解決する引数を持つことです。バリアントがあります:

すべてのバリアントを関数に渡し、特定のバリアントのみを使用します。

class A {
public:
    virtual void set( int, double ) = 0;
};
class B {
   int y;
public:
   virtual void set( int val, double ) { y = val; }
};
class C {
   double y;
public:
   virtual void set( int , double val ) { y = val; }
};

これはあまり良い解決策ではなく、うまくスケーリングできないため、ユニオンを使用できます。

Union Arg {
   int i;
   double d;
};

class A {
public:
    virtual void set( Arg a ) = 0;
};
// derived classes are trivial, so omitted

Union はタイプ セーフではないため、代わりに boost::variant を使用できます

パラメータの別の階層を持つ別のソリューション:

struct Arg {
    virtual ~Arg();
};
struct IntArg : Arg {
    int m_value;
};
struct DoubleArg : Arg {
    double m_value;
};
class A {
    virtual void set( const Arg &a ) = 0;
};
class B {
   int y;
public:
   virtual void set( const Arg &a ) { y = dynamic_cast<const IntArg &>( a ).m_value; }
};
class C {
    double y;
public:
   virtual void set( const Arg &a ) { y = dynamic_cast<const DoubleArg &>( a ).m_value; }
};

static_cast を使用すると、Arg に仮想デストラクタは必要なくなりますが、安全性は低くなります。

これらはほんの一部のバリアントであり、プログラムの要件に基づいてのみ決定できる最も適したものは他にもある可能性があります.

于 2013-02-24T19:57:04.197 に答える
1

継承と仮想のものを捨てます。仮想関数を介して、静的に不明な型の結果に簡単にアクセスすることはできません。そう:

class A
{
private:
    int x_;
public:
    A( int const t = 1 ): x_( t ) {}
};

class B
   : public A
{
private:
    int y_;
public:
    void set( int const y );
};

class C
    : public A
{
private:
    double y_;
public:
    void set( double const y );
};

int main ()
{
    B b; // OK
    C c; // OK
}

クラスの末尾にあるセミコロンAint mainvoid main.

そのような詳細は重要です。

そうでなければ、あなたを助けたいと思っている人々を、長い野生のガチョウの追跡に送ることができます. そして、あなたはそれを望んでいませんよね?したがって、表示したい問題のある部分がコンパイルされない可能性を除いて、投稿するコードがコンパイラによって受け入れられていることを確認してください。

于 2013-02-24T19:57:14.630 に答える
0

秘訣は、BとCの共通部分を見つけて、それらを基本クラスに配置することです。異なるものは、派生クラスのコンストラクターパラメーターに移動する必要があります。

class A { 
   virtual std::string get() const=0;
   virtual void set(std::string s)=0; 
};
class B : public A { B(int a) : a(a) { } int a; };
class C : public A { C(float b) : b(b) { } float b; }

関数を実装するには、次のものが必要です。

void B::set(std::string s) {
   stringstream ss(s);
   ss >> a; 
}
void C::set(std::string s) {
   stringstream ss(s);
   ss >> b;
}

関数は同じように見えますが、実際には異なる演算子を呼び出しています>>。

于 2013-02-24T19:44:29.617 に答える