Re[2]: Преобразовать указатель на член в указатель на класс
От: Tscheineg  
Дата: 09.11.10 15:31
Оценка:
J>А что за задача возникла, что такое понадобилось?

Для чего это может быть нужно?

Пусть есть классы Фу и Бар, причем классу Бар для работы нужно обращаться к объекту класса Фу. Естественное решение — иметь внутри класса Бар ссылку на объект Фу:
class Foo {
 public:
  void Do() {}
};

class Bar1 {
 public:
  Bar1(Foo &foo)
   : m_foo(foo) {}
  
 public:
  void Do() { m_foo.Do(); }
  
 private:
  Foo &m_foo;
};


Поскольку Бар должен работать в содружестве с Фу, то естественно сделать класс-оболочку Фубар, который будет содержать в себе и Фу, и Бар:
class Foobar1 {
 public:
  Foobar1()
   : m_bar(m_foo) {}
   
 public:
  void Do() { m_bar.Do(); }

 private:
  Foo m_foo;
  Bar1 m_bar;
};


А теперь подумаем. Зачем m_bar содержит в себе ссылку на лежащий рядом с ним m_foo?
Ведь m_bar знает указатель на себя (свой this), а компилятор знает смещение между m_foo и m_bar. То есть, m_bar может вычислить указатель на m_foo, и хранить его не нужно.

Так что, если предполагается, что Фу и Бар всегда будут использоваться в составе некой Фубар-оболочки, то, теоретически можно было бы выкинуть из Бара ссылку на Фу, заменить ее этакой compile-time ссылкой.

Что-то вроде того:

template <typename FOOBAR>
class Bar2 {
 public:
  void Do() { RetrieveFoo().Do(); }
  
 private:
  Foo& RetrieveFoo() { return member_cast<FOOBAR&>(*this).m_foo; }
};

class Foobar2 {
 public:
  void Do() { m_bar.Do(); }

 private:
  Foo m_foo;
  Bar2<Foobar2> m_bar;
};


Отмечу также еще пару достоинств такого подхода.
У Foobar1 есть явные проблемы с копируемостью. У Foobar2 их нет.
У Bar2 и Foobar2 нет дурацких конструкторов, которые были у Bar1 и Foobar1
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.