2013-03-11 3 views
1

Возможно ли перегрузить оператор только для одной функции. Я хочу переопределить оператор '->', но только когда он вызывается с функцией печати (-> print()). Я понимаю, что это странный запрос, но я работаю над выполнением определенного API, и мне нужно что-то вроде этого.Оператор перегрузки для вызова функции

Например:

Cat cat; 
cat.walk(); 
cat->print(); //I want to overload only this call 

Однако, я не хочу перегружать '->' оператора для всех случаев. Например:

Cat* cat; 
cat->walk(); //this should work normally 
cat->print(); //this wouldn't call the print() function, 
       //since I overloaded cat->print() 
+0

'Cat * cat; cat-> print(); 'Что именно это должно было бы делать? Не следует компилировать или что? – jrok

+1

Обратите внимание, что если левая часть '->' является указателем, оператор стрелки всегда имеет свой встроенный смысл, и никакой 'operator->' не изменит то, что означает выражение. – aschepler

ответ

4

Вы можете перегрузить оператор -> с фиктивным объектом возврата. Метод true print() может быть закрыт и доступен только через аксессуар. В минимальном примере:

#include <iostream> 

struct Cat; 

struct CatAccessor { 
private: 
    friend class Cat; 
    CatAccessor(Cat& cat) : cat(cat) {} 
    Cat& cat; 
public: 
    void print(); 
    CatAccessor* operator->() { return this; } 
}; 

struct Cat { 
    CatAccessor* operator->() { return CatAccessor(*this); } 
    void walk() { std::cerr << "Walk called" << std::endl; } 
private: 
    void print() { std::cerr << "Print called" << std::endl; } 
    friend class CatAccessor; 
}; 

void CatAccessor::print() { cat.print(); } 

int main() { 
    Cat cat; 
    cat.walk(); 
    cat->print(); 
    Cat* catp = &cat; 
    catp->walk(); 
    // error: catp->print(); 
    return 0; 
} 
+0

Как насчет того, можно ли вызвать какой-либо другой метод Cat? –

+0

@IvayloStrandjev: Как обычно в классе 'Cat'. Обновлен пример. – thiton

+0

Это немного неэффективно, так как каждый экземпляр 'Cat' теперь содержит« CatAccessor ». Я думаю, что это можно было бы улучшить, вернув экземпляр «CatAccessor» из 'operator->' и добавив еще один 'operator->' в 'CatAccessor', используя свойство chaining' operator-> '. –

2

C++ не позволяет делать такие вещи «прямо». Лучший снимок, который у вас есть, - наследовать от класса Cat, сделать метод печати виртуальным и реализовать его по-другому в дочернем классе.

+0

downvoter не могли бы вы указать, что неправильно в моем ответе? –

+0

C++ позволяет вам это делать, как показал Дэниел Фрей. Поэтому я считаю, что ответ ложный. – thiton

+0

@thiton, пожалуйста, предоставьте полный и компилируемый код, который будет делать то, что вы предлагаете –

3

Если вы можете переместить print() в базовый класс, это довольно легко:

class CatBase 
{ 
public: 
    void print(); 
}; 

class Cat : private CatBase 
{ 
public: 
    void walk(); 

    CatBase* operator->() { return this; } 
    const CatBase* operator->() const { return this; } 
}; 
+1

В этом случае 'Cat * c; c-> print(); 'все равно будет работать. – Chad

+0

@jrok: Да, спасибо! :) –

+1

@ DanielFrey: Хороший подход. Если вы создали 'CatBase' частную базу, вы могли бы выполнить требование print(), которое не может быть вызвано напрямую. – thiton

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