首先:我已经阅读过并且现在知道虚拟模板成员函数在 C++ 中(还?) 不可能。解决方法是使类成为模板,然后在成员函数中也使用模板参数。
但在 OOP 的背景下,我发现如果该类实际上是一个模板,下面的示例就不会很“自然”。请注意,该代码实际上不起作用,但 gcc-4.3.4 报告:error: templates may not be ‘virtual’
#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;
}
所以创建一个“Fishfoo”有点奇怪。然而,我似乎希望为每只动物提供任意数量的食物。
因此,我正在寻找一个关于如何实现类似目标的解决方案
Fish bar;
bar.eat( SomeAmount food );
当查看 for 循环时,这变得特别有用。人们可能想给所有不同的动物喂食特定数量(FoodAmount)(例如通过 eat() 和 bind1st()),但这并不容易做到,尽管我觉得这非常直观(因此在某种程度上) “自然”)。虽然现在有些人可能想争辩说这是由于向量的“统一”特征造成的,但我认为/希望应该可以实现这一目标,而且我真的很想知道如何实现,因为这是困扰我好一段时间了……
[EDIT]
也许为了澄清我的问题背后的动机,我想编写一个 Exporter 类并让不同的、更专业的类从中派生。虽然顶级 Exporter 类通常仅用于装饰/结构目的,但派生了 GraphExporter 类,它应该再次作为更专业导出的基类。但是,与 Animal 示例类似,我希望能够在专用/派生类(例如在 SpecialGraphExplorer 上)上定义 GraphExporter*,但在调用“write( out_file )”时,它应该为 SpecialGraphExporter 调用适当的成员函数GraphExporter::write(out_file)。
也许这让我的处境和意图更加清晰。
Best,
Shadow
经过一番思考,我认为这是经典多方法要求,即根据运行时类型多个参数。常见的虚函数有single dispatch
相比之下(他们调度的类型this
only).
请参考以下内容:
- Andrei Alexandrescu has written (the seminal bits for C++?) on implementing multi-methods using generics in 'Modern C++ design'
-
第11章:“多种方法”- 它实现了基本的多方法,使它们对数(使用有序类型列表),然后一直到恒定时间多方法。相当强大的东西!
- A codeproject article that seems to have just such an implementation:
- 不使用任何类型的类型转换(动态、静态、重新解释、const 或 C 风格)
- 不使用 RTTI;
- 不使用预处理器;
- 强类型安全;
- 单独编译;
- 多方法执行的恒定时间;
- 多方法调用期间没有动态内存分配(通过 new 或 malloc);
- 不使用非标准库;
- 仅使用标准 C++ 功能。
-
C++ 开放方法编译器、彼得·皮克鲍尔、尤里·索洛德基和比亚尼·斯特鲁斯特鲁普
- 洛基图书馆有多调度程序
- 维基百科有一个相当不错的简单的写法包含有关 C++ 中的多重调度的示例。
以下是维基百科文章中的“简单”方法供参考(不太简单的方法对于大量派生类型可以更好地扩展):
// Example using run time type comparison via dynamic_cast
struct Thing {
virtual void collideWith(Thing& other) = 0;
}
struct Asteroid : Thing {
void collideWith(Thing& other) {
// dynamic_cast to a pointer type returns NULL if the cast fails
// (dynamic_cast to a reference type would throw an exception on failure)
if (Asteroid* asteroid = dynamic_cast<Asteroid*>(&other)) {
// handle Asteroid-Asteroid collision
} else if (Spaceship* spaceship = dynamic_cast<Spaceship*>(&other)) {
// handle Asteroid-Spaceship collision
} else {
// default collision handling here
}
}
}
struct Spaceship : Thing {
void collideWith(Thing& other) {
if (Asteroid* asteroid = dynamic_cast<Asteroid*>(&other)) {
// handle Spaceship-Asteroid collision
} else if (Spaceship* spaceship = dynamic_cast<Spaceship*>(&other)) {
// handle Spaceship-Spaceship collision
} else {
// default collision handling here
}
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)