2009-03-01 3 views
1

Достаточно ли иметь статическую переменную-член, определенную в базовом классе, и иметь несколько производных классов, каждый из которых использует свой собственный экземпляр этой переменной-члена?переменная статического члена класса подкласса

Следующий код успешно компилируется и печатает правильный вывод, но я все еще не уверен, что делать что-то подобное является хорошей практикой. В следующем примере, как он может работать, если я явно определяю только один экземпляр s (вызывая: string A :: s;), но я фактически использую 2 экземпляра?

class A 
{ 
    protected: 
    void SetS(string new_s){s = new_s;} 
    void PrintS(){cout << s << endl;}; 
    private: 
    static string s; 

}; 

class B : public A 
{ 
    public: 
    void foo(){ SetS("bbb"); PrintS();}; 
}; 

class C : public A 
{ 
    public: 
    void foo(){ SetS("ccc"); PrintS();}; 
}; 

string A::s; 

int main() 
{ 
    B b; 
    b.foo(); // results in output: bbb 
    C c; 
    c.foo(); // results in output: ccc 
    b.foo(); // results in output: bbb 
} 

ответ

7

очень странное использование наследования действительно. Предполагается, что базовый класс должен идеально определять интерфейсы и содержать как можно меньше или вообще не состояние, если это возможно, в соответствии с хорошим принципом разработки OO.

Это работает, потому что ваш foo() сбрасывает значение A::s каждый раз, когда он называется. Попробуйте распечатать адрес A::s. Существует один и только один объект. Это не будет работать, если вы не установите значение каждый раз, и у вас есть несколько объектов, используя другую функцию-член bar(), чтобы прочитать значение A :: s.

Вы можете столкнуться с проблемами синхронизации, если B и C объекты создаются в отдельных потоках. Вы получите UB.

+0

Отличный ответ. +1. –

+0

Спасибо, он полностью ответил на мой вопрос. –

+0

Базовый класс должен определять интерфейсы. Но базовый класс может быть просто рабочим расширением. –

Смежные вопросы