2016-11-18 8 views
2

У меня есть на структуруПерегрузки функцию-член, на который указывает смарт-указатель

struct A { 
    void f() {} 
    void g() {} 
}; 

и пользовательский смарт-указатель держит указатель A:

struct P { 
    ... 
    A* a; 
}; 

Я хотел бы написать P в такой так, что, что A :: F() не дозвонились, когда я пишу

P p; 
p->f(); 

Вместо перегруженная функция должна быть вызвана. Однако, A :: г() должен еще дозвонились, когда я пишу

p->g(); 

Я надеялся, что я могу добиться этого путем перегрузки P :: operator-> но у меня не получилось. Какие-либо предложения?

Edit: Вот что я пробовал:

#include <iostream> 

struct A { 
    void f() {} 
    void g() {} 
}; 

struct P { 
    struct Wrapper 
    { 
     Wrapper(A* aa) : _a(aa) {} 
     void f() 
     { 
     std::cout << "Overloaded\n"; 
     } 
     A* operator->() 
     { 
     return _a; 
     } 
     private: 
     A* _a; 
    }; 

    Wrapper operator->() 
    { 
     return Wrapper(a); 
    } 
    private: 
    A* a; 
}; 

main() 
{ 
    P p; 
    p->f(); 
} 

Но это ничего не печатает вообще, потому что, когда я называю p-> е(), обертка :: operator-> вызывается вместо Wrapper: : F().

+0

, если это ваш собственный смарт-указатель, чем вы можете делать все, что захотите. Я действительно не понимаю вопрос – user463035818

+0

Что вы пробовали? Какие проблемы у вас были с этой попыткой? «Не удалось» не является полезным описанием. – user2079303

+0

марка '->' вернуть некоторую оболочку, которая перенаправляет вызовы 'г()' 'называть Безотносительно :: г()' и 'вызовы F()' 'вызвать A :: F()' – user463035818

ответ

1

Ваш P::operator->, как правило, возвращают A* сырой указатель. Чтобы получить то, что вы хотите, вам нужен объект proxy, который может быть возвращен вместо этого, который реализует эти функции.

class A_proxy 
{ 
    A* p; 
public: 
    A_proxy(A* ptr) : p(ptr) {} 
    void f() { /* do whatever crazy stuff you want here */ } 
    void g() { p->g(); } 
}; 

A_proxy* P::operator->() 
{ 
    return &m_proxy; 
} 

Вот альтернативный метод, основанный на возражениях, высказанных в комментариях. Однако это может привести к неопределенному поведению из-за типа punning указателя.

struct A_proxy : public A 
{ 
    void f() { /* as before, crazy stuff here */ } 
}; 

A_proxy* P::operator->() 
{ 
    return static_cast<A_proxy*>(a); 
} 
+0

Проблема в том, что на самом деле A велико, и я не хочу повторять каждую из своих функций в умном указателе. Я просто хочу перегрузить (отключить) один. –

+0

@DraganVidovic вы можете иметь публичный подкласс 'A_proxy' от' A', так что вы получите бесплатную отправку. –

+0

A тяжелый, я не хочу его снова строить. Я не хочу его копировать, я хочу сослаться на исходный объект, переданный P во время строительства. Если прокси получен из A, то P не является легкой оболочкой вокруг указателя, который должен быть интеллектуальным указателем. –