Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> О правилах видимости членов класса... 
:(
    Опции темы
Chaos A.D.
Дата 24.11.2005, 10:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 172
Регистрация: 16.1.2005
Где: 09 RUS

Репутация: 6
Всего: 7



Подскажите, пожалуйста, разве субкласс не имеет доступа к защищенным функциям класса? У меня не компилится похожий код (GCC 3.какой-то, VC++ .NET) :

Код

template <class T>
class StackImpl
{
    protected :
        T *v_;
        size_t used_;
        size_t size_;

        /* всякие-там конструкторы и т.п. */

        void swap( StackImpl &s )
        {
            std::swap( v_,       s.v_       );
            std::swap( used_, s.used_ );
            std::swap( size_,   s.size_  );
        }
};

template <class T>
class Stack : StackImpl<T>
{
        typedef StackImpl<T> Base;

        void swap( Stack &s )
        {
            static_cast<Base&>(s).swap( static_cast<Base&>(*this) );
        }

    public :

        /* поскипано */

        Stack( const Stack &s )
        {
            Stack(s).swap(*this);
        }
};


Оба компилера отказываются вызывать из Stack<T>::swap функцию StackImpl<T>::swap, мотивируя это тем, что Stack<T> якобы не имеет доступа к базовому. Интересно, что нашло на оба моих компилера? Если бы его претензии к моему коду были бы подкреплены стандартом языка, тогда я не мог бы приводить ссылку на Stack<T> к ссылке на StackImpl<T>.

Под рукой нет Страуструпа, но на память помню, что вроде-бы члены классов могут приводить указатели и все такое, и имеют право вызывать защищенные функции базовых классов. Или я ошибаюсь?
--------------------
Надо смеяться над тем, что тебя мучит, иначе не сохранишь равновесия, иначе мир сведет тебя с ума...Ken Kesey - One Flew Over The Cocoo's Nest
PM MAIL   Вверх
Mayk
Дата 24.11.2005, 13:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


Профиль
Группа: Участник
Сообщений: 2616
Регистрация: 22.5.2005
Где: за границей разум а

Репутация: 45
Всего: 134



Ну значит не имеет, если ты обращаешься просто к экземпляру базовго класса. Собсно зачем это надо, копаться во внутренностях экземпляра родителя?
На
Код

       typedef StackImpl<T> Base;
        void swap( Stack &s )
        {
            Base::swap(*this);
        }

Комо не ругается. А ему можно верить. Гнусовое имхо совпадает с имхо хомяка.
Кстати, у тебя ошибка -
Код

        Stack( const Stack &s )
        {
            Stack(s).swap(*this);
        }

Конструктор вызывает сам себя.


--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
Chaos A.D.
Дата 24.11.2005, 15:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 172
Регистрация: 16.1.2005
Где: 09 RUS

Репутация: 6
Всего: 7



Цитата(Mayk @ 24.11.2005, 13:56)
Конструктор вызывает сам себя.

Да, я и сам после того, как запостил, заметил.
Просто писал сразу в форум, по памяти.
На самом деле это у меня должна была быть реализация копирующего присваивания.

Цитата(Mayk @ 24.11.2005, 13:56)

Ну значит не имеет, если ты обращаешься просто к экземпляру базовго класса.


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

Это сообщение отредактировал(а) Chaos A.D. - 24.11.2005, 15:45
--------------------
Надо смеяться над тем, что тебя мучит, иначе не сохранишь равновесия, иначе мир сведет тебя с ума...Ken Kesey - One Flew Over The Cocoo's Nest
PM MAIL   Вверх
S.A.P.
Дата 24.11.2005, 16:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2664
Регистрация: 11.6.2004

Репутация: 9
Всего: 71



У меня VC и MinGW код компилят... Сам ничего не скажу smile ( вроде так и должно ).

А почти счастливым обладателем стандарта может стать любой желающий

Добавлено 17:26

наверное ты там объявил swap как private. protected, как сейчас должен работать по идее.

Это сообщение отредактировал(а) Perchilla - 24.11.2005, 17:24
PM MAIL   Вверх
Chaos A.D.
Дата 24.11.2005, 19:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 172
Регистрация: 16.1.2005
Где: 09 RUS

Репутация: 6
Всего: 7



Вот более-менее полный код, демонстрирующий эту траблу...
Код

namespace StackSpace
{
    template <class T>
    inline void 
    Construct( T *p, const T &t )
    { new (p) T(t); }

    template <class T>
    inline void 
    Destroy( T *p )
    { p->~T(); }

    template <class T>
    inline void 
    Destroy( T *begin, T *end )
    { 
        while( begin != end )
            Destroy(begin++);
    }
};

template <class T>
class StackImpl
{
    protected :
        
        size_t size_;
        size_t used_;
        T *v_;

        StackImpl( size_t size )
            : size_(size)
            , used_(0)
            , v_( static_cast<T*>( operator new (sizeof(T) * size_) ) )
        {}

        ~StackImpl( void )
        {
            StackSpace::Destroy(v_, v_ + used_);
            operator delete(v_); 
        }

        void swap( StackImpl &other )
        {
            std::swap( v_   , other.v_    );
            std::swap( used_, other.used_ );
            std::swap( size_, other.size_ );
        }

    private :
        StackImpl( const StackImpl & );             // Unable to copy.
        StackImpl& operator=( const StackImpl & );  // Unable to assign.
};

//---------------------------------------------------------------------------

template <class T>
class Stack : public StackImpl<T>
{
        typedef StackImpl<T> Base;

    public :
        Stack( void ) : Base(10) {}
        
        Stack( const Stack &s ) : Base( s.used_ )
        {
            while( used_ < s.used_ )
            {
                StackSpace::Construct( v_ + used_, 
                    s.v_[used_] );

                ++used_;
            }
        }

        Stack& operator=( const Stack &s )
        {
            if ( &s != this )
                Stack(s).swap(*this);
            return *this;
        }

        void swap( Stack &other )
        {
            static_cast<Base&>(*this).swap( static_cast<Base&>(other) );
        }
};


Если заменить в Stack<T>::swap
Код

static_cast<Base&>(*this).swap( static_cast<Base&>(other) );

на
Код

this->Base::swap( static_cast<Base&>(other) );
, все работает. Однако, первоначальный вариант также отказался компилить BCB 6.

Это сообщение отредактировал(а) Chaos A.D. - 24.11.2005, 19:45
--------------------
Надо смеяться над тем, что тебя мучит, иначе не сохранишь равновесия, иначе мир сведет тебя с ума...Ken Kesey - One Flew Over The Cocoo's Nest
PM MAIL   Вверх
LPBOY
Дата 25.11.2005, 19:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 228
Регистрация: 12.7.2005

Репутация: 20
Всего: 20



Цитата(Chaos @ 24.11.2005, 15:39)
А может кто-нибудь из счастливых обладателей копии стандарта пояснит, как там сказано на этот счет?

Видимо компиляторы глючат. Нет причин закрывать доступ к swap.
Кстати, для имен зависящих от параметра шаблона надо использовать уточнение, например, this->.
Такой код компилирует comeau on-line.
Код

#include <cstddef>
#include <algorithm>

namespace StackSpace
{
    template <class T>
    inline void 
    Construct( T *p, const T &t )
    { new (p) T(t); }
    template <class T>
    inline void 
    Destroy( T *p )
    { p->~T(); }
    template <class T>
    inline void 
    Destroy( T *begin, T *end )
    { 
        while( begin != end )
            Destroy(begin++);
    }
}
template <class T>
class StackImpl
{
    protected :
        
        size_t size_;
        size_t used_;
        T *v_;
        StackImpl( size_t size )
            : size_(size)
            , used_(0)
            , v_( static_cast<T*>( operator new (sizeof(T) * size_) ) )
        {}
        ~StackImpl( void )
        {
            StackSpace::Destroy(v_, v_ + used_);
            operator delete(v_); 
        }
        void swap( StackImpl &other )
        {
            std::swap( v_   , other.v_    );
            std::swap( used_, other.used_ );
            std::swap( size_, other.size_ );
        }
    private :
        StackImpl( const StackImpl & );             // Unable to copy.
        StackImpl& operator=( const StackImpl & );  // Unable to assign.
};
//---------------------------------------------------------------------------
template <class T>
class Stack : public StackImpl<T>
{
        typedef StackImpl<T> Base;
    public :
        Stack( void ) : Base(10) {}
        
        Stack( const Stack &s ) : Base( s.used_ )
        {
            while( this->used_ < s.used_ )
            {
                StackSpace::Construct( this->v_ + this->used_, 
                    s.v_[this->used_] );
                ++this->used_;
            }
        }
        Stack& operator=( const Stack &s )
        {
            if ( &s != this )
                Stack(s).swap(*this);
            return *this;
        }
        void swap( Stack &other )
        {
            static_cast<Base&>(*this).swap( static_cast<Base&>(other) );
        }
};

--------------------
Каждый человек по-своему прав, а по-моему нет...
PM MAIL   Вверх
LPBOY
Дата 25.11.2005, 20:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 228
Регистрация: 12.7.2005

Репутация: 20
Всего: 20



Возможно лучше будет вместо
Код

        void swap( Stack &other )
        {
            static_cast<Base&>(*this).swap( static_cast<Base&>(other) );
        }

сделать так:
Код

        void swap( Stack &other )
        {
            Base::swap(other);
        }

или объявить Base::swap в производном классе в public секции с помощью using:
Код

using Base::swap;

или сразу объявить ее в базовом классе открытой.
--------------------
Каждый человек по-своему прав, а по-моему нет...
PM MAIL   Вверх
Chaos A.D.
Дата 26.11.2005, 22:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 172
Регистрация: 16.1.2005
Где: 09 RUS

Репутация: 6
Всего: 7



Цитата(LPBOY @ 25.11.2005, 20:23)
Возможно лучше будет вместо

[поскипано]

сделать так:

[тоже skip]

или объявить Base::swap в производном классе в public секции с помощью using:

[пропустил...]

или сразу объявить ее в базовом классе открытой.


Спасибо за советы. Это у меня был тестовый пример. Заставить работать я его мог, но было интересно, почему не работает так, как было в исходном варианте. Похоже, действительно, компилеры глючат. Надо качать новый гнус...
--------------------
Надо смеяться над тем, что тебя мучит, иначе не сохранишь равновесия, иначе мир сведет тебя с ума...Ken Kesey - One Flew Over The Cocoo's Nest
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0537 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.