Функция-друг, вызывающая статические члены производных классов.Не получается ожидаемый результат - PullRequest
2 голосов
/ 20 января 2012

Мой первый пост здесь:)

У меня проблема со следующим кодом C ++. У меня есть класс ABC A и два производных класса B и C. Все они имеют статический член с именем id:

using std::cout;

class A
{
private:
    friend int bar(A& a);
    static const int id = 1;

    virtual void foo() = 0;
};

class B : public A
{
private :
    friend int bar(A& a);
    static const int id = 2;

    void foo() { /*Do something*/ }
};

class C : public A
{
private:
    friend int bar(A& a);
    static const int id = 3;

    void foo() { /*Do something*/ }
};

int bar(A& a)
{
    return a.id;
}

int main()
{
    B b;
    C c;

    cout << bar(b) << "\n";
    cout << bar(c) << "\n";

    return 0;
}

Я ожидал, что этот код выведет 2 и 3, скорее он выводит 1 и 1 (bar () всегда использует A :: id). Что я делаю неправильно? Есть идеи?


Исходя из комментариев ниже, это последний код, который я использую. Это работает, но хотелось бы услышать больше мыслей:)

#include <iostream>

using std::cout;

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

class B : public A
{
private:
    template <typename T>
    friend int bar(T& t);

    static const int id = 2;
    void foo() { /*do something*/ }
};

class C : public A
{
private:
    template <typename T>
    friend int bar(T& t);

    static const int id = 3;
    void foo() { /*do something*/ }
};


template <typename T>
int bar(T& t)
{
    return t.id;
}


int main()
{
    B b;
    C c;

    cout << bar(b) << "\n";
    cout << bar(c) << "\n";

    return 0;
}

Ответы [ 2 ]

2 голосов
/ 20 января 2012

a.id будет определено во время компиляции как A::id. Вам необходимо определить виртуальную (нестатическую) функцию-член в классе A и переопределить ее в B и C, чтобы вернуть соответствующие id s и вызвать эту функцию в bar.

1 голос
/ 20 января 2012

Есть ли способ избежать написания int foo() { return id; } для всех производных классов?

Да, используя шаблоны.Например:

template <typename T>
int foo (T& x)
{
    return x.id;
}

Однако, если id является закрытым, это не сильно сократит код.

...