C++ 不使用虚函数的多态行为
我正在为一个微控制器开发一种玩具语言,我有一个函数类,它有11个虚拟方法,称为“调用”,从没有参数到10个参数,所有这些参数都接受一个基本对象类并返回一个对象类(函数也扩展了对象)。当我的语言中有函数定义时,我会定义一个类来扩展函数类,并根据其参数实现一个虚拟方法。每当我想调用一个函数时,我就把它转换成一个函数*并用它的参数调用它的call方法。所以我得到了如下结果C++ 不使用虚函数的多态行为,c++,c,oop,C++,C,Oop,我正在为一个微控制器开发一种玩具语言,我有一个函数类,它有11个虚拟方法,称为“调用”,从没有参数到10个参数,所有这些参数都接受一个基本对象类并返回一个对象类(函数也扩展了对象)。当我的语言中有函数定义时,我会定义一个类来扩展函数类,并根据其参数实现一个虚拟方法。每当我想调用一个函数时,我就把它转换成一个函数*并用它的参数调用它的call方法。所以我得到了如下结果 class object {} //other types that extend object class Functi
class object {}
//other types that extend object
class Function : public object{
virtual object* call(){}
virtual object* call(Object* a){}
//....
}
//
// then during code generation I define
//
class s243 : public Function{
Object* call(){
//do somthig
}
}
现在,对于每个扩展函数的类,都会有一个虚拟函数表,每个实例都会有一个指向该表的指针,我这样做的微控制器只有2kb的内存,我至少会有50 60个函数来做基本的事情,所以我正在寻找避免使用虚拟函数的方法。基类还定义了一个虚拟函数,该函数获取自身的深层副本,容器使用该副本复制对象,而无需将其强制转换为特定类型
编辑:我有很多代码空间,我可以用代码空间换取ram。对于函数指针,函数对象可以保存指向其状态的指针
(define make-adder
(lambda (n)
(lambda (x) (+ x n))))
以90分钟scheme编译器为例,我可以传递一个指向n的指针,这样当它返回一个函数时,它就知道n是什么。为什么不使用函数指针的查找表(数组)来代替继承?下面的代码是一个快速而肮脏的伪代码,可能不会编译,但应该会告诉您一般的想法
enum Functions
{
Func1 = 0,
Func2 = 1
};
void *FunctionPointers[] = { &Function1, &Function2 };
FunctionPointers[Func1]( some_parameter);
您的方法的一个问题是基类提供了一个契约,该契约意味着每个可能的函数签名对每个可能的函数都有效。“函数”的用户不知道哪个签名对函数的给定实例有效。是吗
virtual object* call()
或
至少可以使用函数指针或boost::函数指定预期的签名:
void object* (*funcPtr)(Object*);
boost::function< object* (Object*) > boostFunc;
void object*(*funcPtr)(object*);
boost::function
如果您希望能够无论如何调用任何函数,可以使用boost::bind将任何函数转换为上述签名的函数。然后,您可以轻松地将这些函数存储在一个容器中,并根据需要使用它们
由于所有对函数的调用都没有做任何事情,因此在实现过程中也会浪费周期。由于涉及到运行时多态性,编译器可能无法对此进行优化。为什么不使用函数指针呢?因为函数对象可以保存状态,它需要知道的状态(自由变量)是否在代码生成期间使用其构造函数设置?如果要避免使用虚拟函数,您是否考虑过使用CRTP?@tstenner,函数指针将占用与vtable指针相同的空间,因此不会有太多节省-只有vtable本身,每个类一个。所有函数的类型不同。每一个都有不同数量的参数。@nathan:这相当于使用vtable。因为代码是通过编程生成的,所以boost调用了正确的虚函数。它是一个只有32 kb代码空间的微控制器,它甚至没有标准stl,更不用说boost了。@Hamza,您可以在基类中使用一个“call”方法规范化为更少的虚拟函数,然后通过填写剩余参数将每个签名的子类重定向到内部函数指针。
void object* (*funcPtr)(Object*);
boost::function< object* (Object*) > boostFunc;