C ++ Множественное наследование, видимость базового класса и страшный бриллиант.Повторно выставить базовый класс предков как публичный? - PullRequest
1 голос
/ 19 декабря 2011

Мне нужно абстрагировать большую часть интерфейса от базового класса, сделав его защищенным, но мне также нужен открытый доступ к простому классу предков Object. Могу ли я договориться о страшном алмазе без доступа на запись / редактирование к этим предкам и по-прежнему предоставлять только базовый API, но снова сделать API-интерфейс Object общедоступным?

class Object {
    virtual bool  Equals (const Object &obj) const;
    virtual int  GetHashCode (void) const;
};

class ComplicatedOne : public Object {
    //Lots of funcs I don't want or need.
};

class Line : protected ComplicatedOne, public Object {
    //Some funcs of ComplicatedOne get re-implemented or called by alias here
public:
    virtual bool Equals(const Object &obj) const {
        return Object::Equals(obj);
    }
    virtual int GetHashCode() const {
        return Object::GetHashCode();
    }
};

class Array {
    void Add (Object &obj);
    Object *GetAt (int i);
};

main() {
    Array a;
    a.Add(new Line());
}

Ответы [ 3 ]

2 голосов
/ 19 декабря 2011

Вы можете использовать композицию.

Вы можете хранить экземпляр ComplicatedOne в качестве участника и предоставлять то, что вам нужно.

Таким образом, вы можете защитить его, но у вас никогда не будет ситуации с Алмазом.

Кроме того, если ComplicatedOne является Object, то Line является Object по наследству, поэтому вам не нужно наследовать снова.

1 голос
/ 19 декабря 2011

Вы очень смутно понимаете, в чем заключается ваша настоящая проблема, но для меня это звучит так, как будто вы хотите использовать наследование только для повторного использования кода.
Вы не должны этого делать. Взгляните на эту статью .
Для меня это звучит так, как будто композиция больше, чем вы хотите. Создайте члена вашего ComplicatedOne в строке класса и делегируйте вызовы этому члену. Тогда вам не нужно наследовать от него.

0 голосов
/ 26 декабря 2011
    return Object::Equals(obj);

Это не может быть скомпилировано, потому что это неоднозначно: есть два Object базовых объекта.

Кроме того, преобразование из Line* в Object* является неоднозначным, и неоднозначность не может быть разрешена для второго Object базового класса (в порядке слева направо для базового класса), поэтому вторая Object база не служить любой цели, кроме как создавать трудности.

Непонятно, что именно вы пытаетесь сделать: что представляет класс ComplicatedOne? Почему вы наследуете его, если собираетесь снова переопределить каждую Object виртуальную функцию?

...