2015-07-31 3 views
0

(Я не уверен, что это подпадает под шаблоны или виртуальные функции или некоторые из них).Расширяемые методы базового класса?

Предположим, что у нас есть базовый класс (например, tuple2) с двумя значениями x, y. Этот базовый класс имеет метод «норма», который работает на x, y, такой как (sqrt (x x + y y)).

Теперь мы хотим расширить этот класс таким образом, чтобы:

struct tuple2 
{ 
    double x,y; 
    double norm()      {return sqrt(x*x+y*y);} 
    double dotProd (const tuple2& other) {return other.x*x+other.y*y;} 
} 

struct tuple3:public tuple2 
{ 
    double z; 
} 

tuple3 добавляет одну переменную.

Можно ли определить метод базового класса, чтобы он мог обрабатывать x, y и z вместе без перегрузки?

Функции не идентичны, но имеют одинаковые модели . Я предполагаю, что я ищу какой-то шаблон, который расширяет число переменных, а не только тип?

+1

Как насчет использования 'vector' для передачи произвольного числа чисел в' dotProd'? Вы можете сделать это 'initializer_list', если вам не нравятся копии и динамическая память. – nwp

+1

Ограниченный этим случаем кортежа, он помог бы сохранить переменные-члены в контейнере. [variadic templates] (http://en.cppreference.com/w/cpp/language/parameter_pack) может помочь, но я думаю, что он становится довольно сложным. – stefaanv

+1

@nwp: с помощью вектора добавляются 12-байтовые служебные данные. Взяв пример буквально, мы могли бы просто определить tuple3 с тремя двойниками и использовать его для всего. Нет? –

ответ

0

Абстракция может быть получена путем Наследования и с использованием шаблонов. Но как я решаю, зависит от следующих правил. Если обобщенный класс должен использоваться объектами, имеющими общие операции, используйте шаблоны , если оба атрибута и операции являются общими (аналогичные объекты) делают preffer Inheritance.

Можно ли определить метод базового класса, чтобы он мог обрабатывать x, y и z вместе без перегрузки?

Просто нет! Если функции имеют одинаковый шаблон, я предпочел бы специализацию шаблона.

Примечание: это мои взгляды, я бы очень признателен за тех, кто может их исправить, если они не верны.

0

Я думаю, вы должны взглянуть на это:

http://www.linuxtopia.org/online_books/programming_books/c++_practical_programming/c++_practical_programming_106.html

С вашим примером, было бы:

template <size_t N> 
struct tuple 
{ 
    std::array<double, N> elements; 
    double norm() 
    { 
     double n(0.); 
     for (std::size_t i(0) ; i < N ; ++i) 
      n += std::pow(elements[i], 2.); 
     return std::pow(n, 0.5); 
    } 
}; 

Я понимаю вашу проблему с точкой и другими конкретными функциями. .. Вы должны выбрать, может ли функция быть объявлена ​​внутри или не класса. Если вы хотите поставить определенную функцию внутри (перекрестная продукт работает только с N == 3), используйте enable_if так:

template<bool B, typename T = void> 
using Enable_if = typename std::enable_if<B, T>::type; 

template <size_t N> 
struct tuple 
{ 
    std::array<double, N> elements; 
    double norm() 
    { 
     double n(0.); 
     for (std::size_t i(0) ; i < N ; ++i) 
      n += std::pow(elements[i], 2.); 
     return std::pow(n, 0.5); 
    } 
    template<class THIS = tuple<N>, 
     typename = Enable_if<std::is_same<THIS, tuple<3>>::value>> 
    tuple<3> getCrossProduct(const tuple<3>& other); 
}; 

template <std::size_t N> 
template<class THIS, typename> 
tuple<3> tuple<N>::getCrossProduct(const tuple<3>& other) 
{/*...*/} 

Вы можете сделать много вещей с включить, если внутри класса, за исключением определения двух версий (с разными N) той же функции, которые принимают тот же список аргументов.

Надеюсь, это было бы полезно для ваших нужд.

1

Предлагаю бесплатную функцию. Вы можете указать read an article, что причины, по которым бесплатные функции обычно предпочтительнее функций-членов.

double dotProd(const tuple2 &t1, const tuple2 &t2){ 
    return t1.x * t2.x + t1.y * t2.y; 
} 

double dotProd(const tuple3 &t1, const tuple3 &t2){ 
    return t1.x * t2.x + t1.y * t2.y + t1.z * t2.z; 
} 

Легко писать, легко понять, легко расширить и выполнить очень хорошо.

Я не имел большого успеха, расширяя классы с наследованием на C++ и не рекомендую его.

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