2011-07-28 2 views
1

Существует такой класс:Override стандартной функции, которая является другом класса

#include <iostream> 
#include <cmath> 

class Element { 
private: 
    int val; 
public: 
    Element(int val_){ val = val_;} 
    friend Element std::pow(Element a, int exp); 
}; 

Я хотел бы переопределить стандартную функцию Pow, которая является другом класса Element, работать с объектами моего класса. Однако во время компиляции возникает следующая ошибка:

error: ‘Element std::pow(Element, int)’ should have been declared inside ‘std’ 

Как переопределить стандартную функцию pow?

+0

Почему вы хотите, чтобы переопределить функцию из станда и не использовать функцию «автономной» с именем в другом точно также пространством имен? – Griwes

+0

Я хотел бы написать некоторую математическую функцию, которая принимает аргументы стандартных типов данных и мой собственный тип данных и использует функцию мощности. – scdmb

+0

Затем сделайте эту математическую функцию шаблонизированной по типам и частично специализируйте ее на своих собственных классах, чтобы использовать вашу функцию (обратите внимание, что я не являюсь носителем английского языка, и я не уверен, что «частично специализация» - это правильное выражение здесь, исправьте меня, если я ошибочно). – Griwes

ответ

7

Прежде всего, вы не override, вы overload. Термин override относится к виртуальным функциям, а overload - к выбору правильной функции на основе типов параметров.

Решение прост: не пишите std::pow, просто напишите pow. Или yournamespace::pow, если хотите - не имеет значения. Да, это именно так.

Тогда:

double a; 
Element b; 

using std::pow; 
pow(a, 10.0); // calls std::pow(double, double) 
pow(Element, 10) // calls pow(Element, int) 

Объяснение: В C++ есть дикая вещь называется ADL (или поиск Кенига), который будет в основном решить, какой вариант использовать, и он будет выбирать перегрузку из любого пространства имен без необходимости укажите его в месте вызова.

Есть прочитанный: http://en.wikipedia.org/wiki/Argument-dependent_name_lookup

2

В принципе, вы не можете этого сделать. Во-первых, вам не разрешено помещать определяемые пользователем вещи в пространство имен std.

Вам нужно будет написать свою собственную функцию pow, то есть не внутри std.

-1

Вы должны определить функцию в стандартном пространстве имен, либо его не существует:

namespace std { 
    Element pow(Element a, int exp) { 
     //... 
    } 
} 
+0

-1, загрязнение пространства имен std не является решением. Для решения см. Ответ Оли. – Dialecticus

+0

Вам запрещено делать это по стандарту. –

0

Ну, как для начала Вам не следует добавлять вещи в пространство имен std.

Перегрузка pow должна находиться в отдельном пространстве имен. Затем вы должны быть

using std::pow 
using my::pow; 

дискуссионных точек стиля, что я поддерживаю: общие функции, как это не должны быть пространством имен квалифицированы. То есть, используйте using и вызывайте pow() в код клиента вместо std::pow(), то же самое относится к std::swap и другим точкам настройки.

Единственный раз, когда вы можете расширить пространство имен std с помощью специализированных шаблонов. Снова рассмотрим std::swap.

+0

Является ли хорошей практикой специализироваться на std :: swap (в отличие от перегрузки)? – Kos

+1

Это единственный способ, разрешенный стандартом. – spraff

+1

@ Kos: Вы можете предоставить другую функцию 'swap', которая будет подхвачена ADL и таким образом вам не нужно специализироваться/перегружать ее. Идиомой для вызова 'swap' должно быть, поскольку этот ответ указывает:' void foo (Тип x, Тип y) {с использованием std :: swap; swap (x.a, y.a); } 'Таким образом, он будет искать' swap' как в 'std', так и в пространстве имен, где определен тип' Type :: a'. –

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