13

以下を検討してください。

struct A {
    static const int X = 1;
    static void printX() {std::cout << "X " << X << std::endl; };
};

struct B: public A {
    static const int X = 2;
};

int main(argc argv){
    B b;
    b.printX();
}

強制的にb.printX()値 2 を出力する方法は?
定数とメソッドの両方が静的でなければなりません。したがって、仮想メソッドは適していません。

私の仕事を私よりもよく知っていると思っていて、私がそれを再考するのを見たいと思っている人のために、私の努力の目標を説明します:)
静的定数のセットに基づいた動作を持つクラスを想像してみてください。異なる定数セットを使用して子クラスを実装し、したがって異なる動作を行う最も簡単な方法は、特定の定数値セットを使用して前のクラスからクラスを派生させることです。仮想関数を使用してそのタスクを解決することができます。当然のことながら、疑いの余地はありません。しかし、この解決策は、モデル化されたエンティティの理論に一致するという意味ではあまり純粋ではありません。この場合の仮想メソッドの使用は、正しい実装よりもトリックになります。
たとえば、IR チャネルでは、パルス持続時間とパッケージ構造のタイミングが異なります。特定の定数値のセットを使用して子クラスのセット (さまざまな IR チャネルの実装) を定義すると便利です。その値は、コンパイル時にのみ必要になるため、class および const のすべてのオブジェクトに共通であるため、静的です。また、基本クラスと子クラスの内部実装はわずかに異なるため、それらの間の最適な関係はsuper class - child class.
私の元の質問の根拠は今ですか?

4

6 に答える 6

8

後でわかるように、テンプレートが必要になり、テンプレートを使用するように継承を変更します。トリックは、派生クラスが基本クラスの X を覆い隠す X を持っているかどうかにかかわらず、それを機能させることです。

template<class C>
struct A {
    static const int X = 1;
    template<typename T>
    static int getX(decltype(T::X)*) 
        { return T::X; }
    template<typename T>
    static void getX(...)
        { return X; }
    static void printX()
        { std::cout << "X " << getX<C>(0) << std::endl; }
};

struct B: public A<B> {
    static const int X = 2;
};

struct B2: public A<B2> {
    // No X
};

int main(){
    B b;
    b.printX(); // Prints X 2
    B2 b2;
    b2.printX(); // Prints X 1
}
于 2012-11-12T09:47:29.717 に答える
4

定義上、静的メンバーで行うことはすべて、「オーバーライド」ではなく「オーバーシャ​​ドウ」になります。「B」で「printX()」を再実装することはできますが、実際には動作をオーバーライドすることはありません。これはシャドウイングを使用するため、動作は実行時ではなくコンパイル時のタイプに完全に依存します。

于 2012-11-12T08:03:23.613 に答える
0

簡単な答え: できません。

少し長く、より複雑な答え: まあ、できるかもしれません。テンプレート付き

#include <iostream>

template <typename T> struct A 
{
    static const int X = 1;

    static void printX() 
    { 
        std::cout << "X=" << T::X << std::endl; 
    }
};

struct B : public A<B> 
{
    static const int X = 2;
};

int main(int, char **)
{
    B b;

    b.printX();

    return 0;
}
于 2012-11-12T08:16:05.643 に答える
0

わかりました、一緒に遊んでみます...これを複数のレベルの深さで入れ子にしたいと考えています。罰金。

#include <iostream>

template <int XX> struct T
{
    static const int X = XX;

    static void printX()
    {
        std::cout << "X=" << X << std::endl;
    }   
};

struct AA 
{
    static const int X = 1;

    /* all other members go here */
};

struct A : public AA, public T<AA::X>
{
    /* empty - put stuff in AA instead */
};

struct BB : public AA
{
    static const int X = 2;
};

struct B : public BB, public T<BB::X>
{
};

struct CC : public BB
{
    static const int X = 3;
};

struct C : public CC, public T<CC::X>
{
};

struct DD : public CC
{
    static const int X = 4;
};

struct D : public DD, public T<DD::X>
{
};

int main(int, char **)
{
    A a;
    B b;
    C c;
    D d;

    a.printX();
    b.printX();
    c.printX();
    d.printX();

    return 0;
}

static const int X = ...;すべてのクラスで をスキップして、必要に応じて などを実行することもできpublic T<1>ますpublic T<2>

于 2012-11-12T08:55:35.190 に答える