У меня есть простой базовый класс Shape с его производным классом Ball. Цель состоит в том, чтобы иметь типичность скалярного типа и размеров, следовательно, использование шаблонов.C++ Специализация частичного шаблона по виртуальному методу
#include <iostream>
#include <array>
#include <cmath>
template<typename T, std::size_t DIM>
class Shape {
public:
Shape(std::array<T,DIM> base_point) : base_point_(base_point) {}
virtual T volume() const = 0;
protected:
std::array<T,DIM> base_point_;
};
template<typename T, std::size_t DIM>
class Ball : public Shape<T,DIM> {
public:
Ball(std::array<T,DIM> base_point, T radius) : Shape<T,DIM>(base_point), radius_(radius) {}
virtual T volume() const;
private:
T radius_;
};
// Cannot use the generic code below because of Template may not be 'virtual' ?
// template<typename T>
// T Ball<T,2>::volume() const { return M_PI * radius_ * radius_; }
template<>
float Ball<float,2>::volume() const { return M_PI * radius_ * radius_; }
// template<typename T>
// T Ball<T,3>::volume() const { return 4/3 * M_PI * radius_ * radius_ * radius_; }
template<>
float Ball<float,3>::volume() const { return 4/3 * M_PI * radius_ * radius_ * radius_; }
int main() {
Ball<float,2> circle{{0.2f,0.3f}, 4.0f};
std::cout << circle.volume() << std::endl;
}
Я бы хотел использовать частную специализацию по шаблону, чтобы вычислить том в зависимости от размера. Код работает, но является громоздким, если я должен специализироваться на другом типе, таком как double (код будет таким же).
Я знаю, что я не могу иметь частичную шаблонную специализацию для виртуальных методов, но когда я использую комментируемой выше код у меня есть следующие ошибки вместо Ошибки: Шаблон не может быть «виртуальным»:
shape_generic_naive.cpp:24:25: error: invalid use of incomplete type ‘class Sphere<T, 2ul>’
T Sphere<T,2>::volume() const {return M_PI * radius_ * radius_; }
^
shape_generic_naive.cpp:15:7: error: declaration of ‘class Sphere<T, 2ul>’
class Sphere : public Shape<T,DIM> {
Я действительно не получаю эту ошибку, как ее избежать и какие способы элегантности этой родословности?
'BallVolume' должны быть объявлены до' Ball' или 'функции члена volume' определено позже –
@ PiotrS. Или читатель применяет здравый смысл при чтении ответа. Я не '# include' заголовок для' std :: size_t' тоже. Но на всякий случай я отменил заказ. – Angew
Спасибо, он отлично работает для меня! Я действительно использовал свой здравый смысл с первого раза;). edit: зачем понадобится static_cast на 3.0? 4.0/3.0 не совсем уверен? –
coincoin