Как добиться «функции виртуального шаблона» в C ++

во-первых: я прочитал и теперь знаю, что функция-член виртуального шаблона невозможна (пока?) В C ++. Обходной путь - сделать класс шаблоном, а затем использовать аргумент шаблона также в функции-члене.

Но в контексте ООП я считаю, что приведенный ниже пример не был бы очень "естественным", если бы класс на самом деле был шаблоном. Обратите внимание, что код на самом деле не работает, но gcc-4.3.4 сообщает: error: шаблоны не могут быть «виртуальными»

#include <iostream>
#include <vector>

class Animal {
    public:
        template< class AMOUNT >
        virtual void eat( AMOUNT amount ) const { 
            std::cout << "I eat like a generic Animal." << std::endl; 
        }
        virtual ~Animal() { 
        }
};

class Wolf : public Animal {
    public:
        template< class AMOUNT >
        void eat( AMOUNT amount) const { 
            std::cout << "I eat like a wolf!" << std::endl; 
        }
        virtual ~Wolf() { 
        }
};

class Fish : public Animal {
    public:
        template< class AMOUNT >
        void eat( AMOUNT amount) const { 
            std::cout << "I eat like a fish!" << std::endl; 
        }
        virtual ~Fish() { 
        }
};

class GoldFish : public Fish {
    public:
        template< class AMOUNT >
        void eat( AMOUNT amount) const { 
            std::cout << "I eat like a goldfish!" << std::endl; 
        }
        virtual ~GoldFish() { 
        }
};

class OtherAnimal : public Animal {
        virtual ~OtherAnimal() { 
        }
};

int main() {
    std::vector<Animal*> animals;
    animals.push_back(new Animal());
    animals.push_back(new Wolf());
    animals.push_back(new Fish());
    animals.push_back(new GoldFish());
    animals.push_back(new OtherAnimal());

    for (std::vector<Animal*>::const_iterator it = animals.begin(); it != animals.end(); ++it) {
        (*it)->eat();
        delete *it;
    }

    return 0;
}

Поэтому создание «Fish foo» выглядит странно. Однако мне кажется желательным предоставить произвольное количество еды для каждого животного.

Таким образом, я ищу решение о том, как достичь чего-то вроде

Fish bar;
bar.eat( SomeAmount food );

Это становится особенно полезным при рассмотрении цикла for .

[EDIT]

Чтобы, возможно, прояснить мотивацию моего вопроса, я хочу запрограммировать класс Exporter и позволить другим, более специализированным классам происходить из него. В то время как класс Exporter верхнего уровня обычно используется только для косметических / структурных целей, класс GraphExporter является производным, который снова должен служить базовым классом для еще более специализированного экспорта. Однако, как и в примере с Animal, я хотел бы иметь возможность определять GraphExporter * даже в специализированных / производных классах (например, в SpecialGraphExplorer), но при вызове «write (out_file)» вместо этого он должен вызывать соответствующую функцию-член для SpecialGraphExporter of GraphExporter :: write (out_file).

Может быть, это проясняет мою ситуацию и мои намерения.

С уважением,

Shadow

41
задан Shadow 3 May 2011 в 18:09
поделиться