Дружба против наследства - PullRequest
3 голосов
/ 27 января 2011

Ниже приведена иерархия классов.По сути, я хотел бы установить отношение «имеет-а» между классами Foo и CComplexMat, то есть класс Foo имеет -А «CComplexMat».Из того, что я знаю, private и protected члены класса не могут быть доступны извне класса, в котором они определены.

Однако есть две возможности разрешить другим классам доступ к таким членам.Первый - использовать friend классы.Я мог бы добавить строку friend class Foo<T>; в объявлении class CComplexMat<T>, чтобы Foo<T> мог получить доступ к protected и private членам class CComplexMat<T>.

Второй возможностью было бы использоватьinheritance, это решение, которое я выбрал в примере.В этом случае я рассматриваю наследование public, чтобы оба члена public и protected из class CComplexMat<T> были доступны в классе Foo<T>.Однако отображается следующая ошибка:

error: ‘CMatrix<float>* CComplexMatrix<float>::m_pReal’ is protected

error: within this context

  1. Мне было интересно, может кто-нибудь пролить свет на ошибку?
  2. В каких ситуациях «дружба» или «наследство» более подходят?
template <class T>
class CMatrix{
    public:
     ...
        CMatrix<T> & operator = (const CMatrix<T> &);
        T & operator()(int, int, int);
        T operator()(int, int, int) const;
     ...
    private:
       T *** pData;
       int rows, cols, ch;
};

template <class T>
class CComplexMat: public CMatrix<T>{
    public:
    ...
    protected:
        CMatrix<T> *pReal;
        CMatrix<T> *pImag;
};

template <class T>
class Foo: public CComplexMat<T>{
    public:
        ...
        void doSomething(){
           ...
           CMatrix<T>*pTmp = pComplex->pReal; // error here.
           ...
        }
    ...
    private:
        CComplexMat<T> * pComplex;
    ...
};

Ответы [ 4 ]

4 голосов
/ 27 января 2011

Наследование должно использоваться только для отношений "is-a". Мне кажется, что CComplexMat<T> имеет два CMatrix<T> члена, но это не тот случай, когда он "is-a" CMatrix<T>. Аналогичная сделка с Foo и CComplexMat<T>.

Таким образом, наследование почти наверняка не является правильным решением. Что оставляет:

  • Используйте friend, чтобы разрешить доступ между тесно связанными классами.
  • Использование общедоступных методов доступа, позволяющих пользователям класса «получать доступ» к закрытым членам ограниченным образом.

Например, CComplexMat<T>, вероятно, должен иметь закрытых членов для реальной и мнимой частей, но также и некоторые методы доступа, такие как:

public:
    const CMatrix<T>& realPart() const;
    CMatrix<T>& realPart();
    const CMatrix<T>& imagPart() const;
    CMatrix<T>& imagPart();
0 голосов
/ 27 января 2011

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

В вашем примере, если pComplex будет указывать наобъект типа Foo, тогда вы можете получить доступ к pReal так, как вы пытаетесь.

0 голосов
/ 27 января 2011

Согласно стандарту C ++ о доступе защищенных членов в производных классах (11.5)

За исключением случаев, когда формируется указатель на член (5.3.1), доступ должен осуществляться через указатель, ссылка или объект самого производного класса (или любого класса, производного от этого класса)

Вы пытаетесь получить доступ к pReal через базовый класс.

Сделайте Foo другом CComplexMat для доступа к его членам.

0 голосов
/ 27 января 2011

Вы обращаетесь к локальной переменной для CComplexMat в своем классе Foo, а не просто обращаетесь к родительскому классу, чтобы получить значение pReal.

Этот учебник разбивает разницу между дружбой и наследованием в C ++.
Обратите внимание, как они обращались к переменным-членам родительского класса напрямую, без локального члена типа родительского класса,Это, вероятно, то, что вы хотите сделать в вашем примере.

...