我正在使用Lua和C ++(使用LuaWrapper),我遇到了麻烦。假设我有这些课程:
class Bar{...};
class Foo
{
...
std::map<std::string,Bar*> _barlist;
...
Bar* getBar(std::string key)
{
return _barlist[key];
}
}
class BarDerived1 : public Bar{...}
class BarDerived2 : public Bar{...}
我可以从Lua访问Foo
和Foo::getBar()
,问题是返回的对象中的类型是Bar
,我无法访问其BarDerivedX
方法。
据我所知,Lua中的对象/类只是MetaTables,其功能分配给键,所以我想知道是否有办法将这些额外的函数从BarDerivedX
类复制到Bar
对象(甚至可以工作吗?),这也是最好的方法,或者我应该在让Lua访问之前用C ++编译它?
答案 0 :(得分:5)
在任何语言中,多态性的目的是不必关心什么类型的东西。如果你给某人(无论是Lua还是C ++)一个Bar
对象,那么Bar
应该有人们需要做的任何接口。
这就是虚拟功能的目的。 Bar
中定义的虚拟函数可以使用BarDerived1
中的不同行为覆盖。其他代码不必知道它们被传递给派生类;他们总是可以像Bar
一样。
通常只有两个理由使一个类派生自另一个。第一个是多态:你想通过改变某些函数的行为来专门化一个类。
另一个原因是获得对其实施的访问权限。例如,如果您正在创建Unicode字符串,则可以使用std :: basic_string来存储编码数据。然后,您可以私有从std :: basic_string派生,从而允许您获得std :: basic_string具有的存储优化,但是您提供了不同的接口(因为私有继承不允许外部世界要知道你是从中衍生出来的。)
如果您希望每个人都使用基于派生类可能具有不同行为的Bar
个对象,那么您应该使用虚函数和多态。但是,如果您在派生类中更改接口,那么这可能是设计问题的一个标志。也许那些派生类根本不应该是派生类。根据一些初始化参数,它们应该是Bar
实例可能有或没有的完全独立的类。
如果没有具体说明你的实际行动,很难说更多。但一般来说,如果您正确使用基于继承的多态,则不需要从Bar
转换为更多派生版本。只需使用Bar
界面。
答案 1 :(得分:2)
类继承有一个基本原则:
必须可以通过其任何子类的实例来交换超类的实例。
如果B是A的子类,那么在您使用A实例的任何地方,您都应该能够使用B的实例。
如果您的代码没有这样做 - 那么只是您没有正确使用继承。确切地说,如果您需要子类的唯一原因是创建集合更简单,那么您没有正确使用它。
正如其他人所说,正确的解决方案是在收集声明中使用“泛型”;完全删除Bar
,并在集合声明中,使用boost::variant
,空指针或工具集中的等效项。