2017-02-14 16 views
-1

Я хотел бы указать несколько объектов с одинаковыми уровнями наследования и для каждого из этих уровней использовать одни и те же данные. Поэтому я думаю о наследовании и статических членах класса.Как делиться одними и теми же данными между несколькими экземплярами на уровнях наследования?

Это мой attempt:

#include <iostream> 

class Father 
{ 
public: 
    static int sValue; 

    inline int GetValue() { return sValue * 10; } 
}; 

class Child1 : public Father 
{ 
public: 
}; 

class Child2 : public Father 
{ 
public: 
}; 

int Father::sValue = 0; 

int main() 
{ 
    Child1 child1_1; 
    Child1 child1_2; 
    Child2 child2_1; 
    Child2 child2_2;  


    child1_1.sValue = 1; 
    child2_1.sValue = 2;  

    std::cout << child1_2.GetValue() << std::endl; 
    std::cout << child2_2.GetValue() << std::endl; 
} 

В моем примере оба Child1 экземпляры должны вернуть 10 с GetValue(), и оба Child2 экземпляры должны вернуть 20 с помощью GetValue(). Поскольку функция такая же, я не хочу переопределять ее для каждого ребенка (поэтому я поместил ее в Father).

Проблема заключается в том, что также Child1 экземпляров возвращает 20 вызовов GetValue().

Таким образом, static является общим для "основного" родителя, а не для ребенка.

В виду того что значение sValue использовано в GetValue(), его правильно поместить его здесь. Но я не могу отделить статические/одинаковые данные.

Как вы это сделаете?

+2

Поместите статический член в каждый производный класс? – LogicStuff

+0

@LogicStuff: нет, иначе я больше не могу использовать 'sValue' внутри GetValue() (которая является общей функцией) ... – markzzz

+2

Затем создайте' virtual' функцию 'GetSValue', которая будет использоваться в' GetValue' , – LogicStuff

ответ

2

splrs пользователь правильно определил проблему и решение является правильным. Вам нужны две разные функции с двумя разными статическими объектами. Вы можете избежать повторения кода, с помощью шаблона:

template<class Child> 
struct Father { 
    static int sValue; 
    int GetValue() { /* ... */ } 
}; 

struct Child1 : Father<Child1> {}; 
struct Child2 : Father<Child2> {}; 

Эта идиома известна как Любопытно повторяющегося рисунка шаблона.


Теперь, разумеется, нет общего родителя. Если вам нужно, вы можете наследовать шаблон из нешаблонной базы:

struct FatherBase {}; 

template<class Child> 
struct Father : FatherBase { /*...*/ }; 

И, если вам нужно получить доступ к различным версиям GetValue из базы, то вам необходима виртуальная функция:

struct FatherBase { 
    virtual int GetValue() = 0; 
}; 

template<class Child> 
struct Father : FatherBase { 
    // ... 
    int GetValue() override { /* ... */ } 
}; 
+0

Не знаете, что вы делаете со структурой. Мне нужен класс. Уникальная функция для всех дочерних элементов и общий статический для каждого класса производного уровня. Можете ли вы привести пример? – markzzz

+0

@paizza Структура - это класс. Я использую его, чтобы сделать пример кратким. Но используйте ключевое слово класса, если хотите. Каждый дочерний класс имеет свой собственный статический член, наследуемый от шаблонного отца, да. Примеры приведены в моем ответе. – user2079303

1

Вы модифицирования Father::sValue при вызове child1_1.sValue = 1; и child2_1.sValue = 2; Там один экземпляр, который принадлежит к Father, так же вы к нему доступ (через метод против классов или экземпляров), вы получите то, что он был установлен в перед на звонок до GetValue().

Если вы хотите получить номер Child1 и Child2, добавьте к этим классам статические элементы и методы.

+0

прочитал мое сообщение. Если я это сделаю, 'GetValue()' не может работать и его общая функция, которая должна использоваться. – markzzz

1

Я думаю, что следующее может быть то, что вы после:

class Father 
{ 
public: 
    inline int GetValue() { return DoGetValue() * 10; } 
    void SetValue(int value) { DoSetValue(value); } 

protected: 
    virtual int DoGetValue() = 0; 
    virtual void DoSetValue(int value) = 0; 
}; 


class Child1 : public Father 
{ 
public: 
    static int sValue; 

protected: 
    int DoGetValue() override { return sValue; } 
    void DoSetValue(int value) override { sValue = value; } 
}; 

class Child2 : public Father 
{ 
public: 
    static int sValue; 

protected: 
    int DoGetValue() override { return sValue; } 
    void DoSetValue(int value) override { sValue = value; } 
}; 

int Child1::sValue = 0; 
int Child2::sValue = 0; 

int main() 
{ 
    Child1 child1_1; 
    Child1 child1_2; 
    Child2 child2_1; 
    Child2 child2_2;  


    child1_1.SetValue(1); 
    child2_1.SetValue(2);  

    std::cout << child1_2.GetValue() << std::endl; 
    std::cout << child2_2.GetValue() << std::endl; 
} 
+0

Это настолько избыточно. Если у меня есть 20 переменных вместо 1 ('sValue'), мне нужно повторно объявить его 20 раз для каждого наследования. То же самое для каждого приемника/сеттера. Я думаю, что я попытаюсь выполнить некоторые операции ''. – markzzz

+1

@paizza, возможно, вы хотите сделать что-то, что невозможно. Или, по крайней мере, я не знаю. – peval27

+0

Это я имел в виду http://www.martin-finke.de/blog/articles/audio-plugins-016-polyphony/. Он говорит, что в какой-то момент: «Кроме того, статичность stageValues ​​EnvelopeGenerator будет означать, что объём и фильтр-конверт всегда одинаковы. Это можно было бы решить путем наследования: мы могли бы создать класс VolumeEnvelope и FilterEnvelope и наследовать от них EnvelopeGenerator. StageValue может быть статическим, и как VolumeEnvelopeand FilterEnvelope может его переопределить ». Что означает переопределение статического члена? – markzzz