2013-12-02 3 views
0

Я разработал класс, назовем его foo. В заголовочном файле я решил иметь класс, содержащий все личные члены foo в разделе private:. Таким образом, если мне нужно редактировать какие-либо частные члены foo, мне не нужно перекомпилировать каждый исходный файл, который использует foo.h. Он создан как таковой:Вызов частных функций во вложенных классах

#ifndef FOO_H 
#define FOO_H 

class fooData; 

class foo 
{ 
    private: 
     fooPrivate *prv; // This class stores foo's private members 
    public: 
     foo(); // Default constructor 
     void bar(); 
} 

#endif 

Мой класс foo.cpp выглядит следующим образом:

#include "foo.h" 

class fooPrivate // Class which stores foo's private members 
{ 
    public: 
     void doMagic(); 
} 

foo::foo() 
{ 
    prv = new fooPrivate; // Instantiate fooPrivate 
    prv->doMagic(); 
} 

void foo::magic() // This is a public member function of foo 
{ 
    std::cout << "Magic!" << std::endl; 
} 

void fooPrivate::doMagic() // This is a function of private member fooPrivate 
{ 
    magic(); // I want to call a public member of foo here 
} 

Большинство из вас уже знают, ошибку я собираюсь от попыток вызвать магию() из результаты в

error: 'magic' was not declared in this scope 

И, изменяя вызов Foo :: магии():

error: cannot call member function 'void foo::magic()' without onject 
doMagic()

Теперь мне бы очень хотелось избежать создания экземпляра объекта типа foo внутри объекта типа fooPrivate, который сам является результатом создания объекта типа foo ... Итак, есть ли способ вызвать public функция-член функции magic() из функции публичного участника fooPrivate?

ответ

3

При создании fooPrivate, передать ссылку на Foo как часть конструктора:

foo::foo() 
{ 
    prv= new fooPrivate(* this) ; 
} 

class fooPrivate 
{ 
    foo & foo_ ; 
    ... 
} 

fooPrivate::fooPrivate(foo & aparen) : foo_(aparen) { } 

Тогда в doMagic() просто называют его по ссылке:

void fooPrivate::doMagic() 
{ 
    foo_.magic() ; 
} 

Кроме того, магазин fooPrivate в unique_ptr, так что, когда foo уничтожается, fooPrivate уничтожается вместе с ним:

class foo 
{ 
    private: 
    std::unique_ptr<fooPrivate> prv ; 

, который для удобства можно инициализировать как:

foo::foo() : prv(new fooPrivate(* this)) { } 

Кстати, я не рекомендую взываю к prv->magic() внутри конструктора, если он затем будет перезвонить в неподвижном создаются foo с вызовом doMagic ,

+0

Реализация вашего решения, я столкнулся с ошибкой: class 'fooPrivate' не имеет поля с именем 'foo_'. " Добавление декларации «foo foo_» в fooPrivate приводит к успешной компиляции, но segfaults также во время выполнения. Редактировать: Я знаю причину и вернусь к вам, если нет. – Answoquest

+0

Извините, что опубликует эту часть определения, позвольте мне изменить. – woolstar

+0

Это исправлено. Отличное объяснение и очень аккуратный трюк. Возможно, вы захотите дополнительно отредактировать свое решение, чтобы добавить закрывающую фигуру после «foo & foo_;», перед «...», как и без нее, похоже, что вы указываете, что «fooPrivate :: fooPrivate (foo & aparen): foo_ (aparen) {} "находится внутри определения класса. Никакой способный кодер не ошибается, что вы указываете, но новичок, спотыкающийся о вашем решении, может запутаться. – Answoquest

Смежные вопросы