简体   繁体   English

c ++虚函数

[英]c++ virtual functions

Just wondering, what would be fastest? 只是想知道,什么会最快? If I had a base class like this 如果我有这样的基类

Class Base
{
virtual void Draw()
{
//something...
}
};

Then I would have an array of Base like this: 然后我会像这样有一个Base数组:

Base Array[255];

Which could contain both Base and it's derivatives. 哪个可能包含Base和它的衍生物。 This would be one way of for example, storing various drawing commands. 这将是例如存储各种绘图命令的一种方式。 (I know this would seem java-like, but it's just for the example. Classes with just one function doesn't make much sense.) (我知道这看起来像java一样,但它只是用于示例。只有一个函数的类没有多大意义。)

Now alternatively, if I knew exactly what derivatives I would make it could be done like this 现在另外,如果我确切地知道我会做什么衍生物就可以这样做

class Base
{
int ID;
};

then an array of Base like before: Base Array[255]; 然后是像以前一样的Base数组:Base Array [255];

And then create the Draw functions in the derivatives: 然后在衍生中创建Draw函数:

class Der1 : Base
{
void Draw()
{
}
};

class Der2 : Base
{
void Draw()
{
}
};

Now, this solution of course doesn't allow me to just loop through the array and call Draw for each object. 现在,这个解决方案当然不允许我循环遍历数组并为每个对象调用Draw。 Instead it would have to be done something like this. 相反,它必须做这样的事情。

void CallDraw()
{
for (int i = 0; i < 255; i++)
{
switch(Array[i].ID)
{
case 1: //Der1
   ( (Der1) Array[i] ) . Draw(); 
case 2: //Der2
   ( (Der2) Array[i] ) . Draw();
}

And yeah, to those who have read so far, the actual question. 对于那些到目前为止已经阅读过的人来说,这是一个实际的问题。 Which would be faster, if you knew the derivatives? 如果你知道衍生品,哪个会更快? Making an organized system yourself, or using virtual functions? 自己制作一个有组织的系统,还是使用虚拟功能?

And are there other things to take into consideration? 还有其他事情需要考虑吗? (code cleanness maybe, but I rather like to show off what my class type is in the code, so I'm not bothered by the casts. (代码清洁可能,但我更喜欢在代码中展示我的类类型,所以我不会被演员打扰。

Definitely use virtual functions, that's precisely what they are for. 绝对使用虚拟功能,这正是它们的用途。 Reimplementing it yourself is error-prone and certainly isn't going to be faster. 自己重新实现它是容易出错的,当然不会更快。

Also, in your declaration of Array you need to use pointers: 此外,在您的Array声明中,您需要使用指针:

Base *Array[255];

Otherwise, in C++ (unlike Java), the array could only contain instances of Base and no objects of derived classes. 否则,在C ++中(与Java不同),该数组只能包含Base实例,而不包含派生类的对象。 Using a pointer is more like Java's references and allows you to put instances of derived class into the array. 使用指针更像是Java的引用,并允许您将派生类的实例放入数组中。

Use virtual functions, because in logical terms they act pretty the same way, but using the virtual function table lookup, which might be slower / faster (depending on the implementation). 使用虚函数,因为在逻辑上它们的行为方式完全相同,但使用虚函数表查找,这可能更慢/更快(取决于实现)。 Still, unless this is the critical part of your code (and that's 99 / 100 cases), don't bother yourself with such kinds of things. 尽管如此,除非这是你的代码的关键部分(并且是99/100个案例),否则不要为这些事情烦恼。

Usage of virtual functions makes your code cleaner and you won't have to bother yourself with problems related to your own implementations of something that already exists as a part of C++. 虚函数的使用使您的代码更清晰 ,您不必担心与您自己实现已经作为C ++的一部分存在的事物相关的问题。

I assume you're asking out of curiosity -- not because you would actually try to implement it with a switch. 我假设你要求出于好奇心 - 不是因为你真的试图用开关来实现它。

You have to make your array Base* , not Base 你必须使你的数组Base* ,而不是Base

A Virtual call is an array lookup and function call. 虚拟调用是数组查找和函数调用。 A switch is often implemented as a simple constant-time jump. 开关通常实现为简单的恒定时间跳转。 So, they are both O(1), but I think the virtual call would be faster since C++ compilers would be optimized to make that fast, and the switch isn't guaranteed to be O(1). 因此,它们都是O(1),但我认为虚拟调用会更快,因为C ++编译器将被优化以使其快速,并且交换机不能保证为O(1)。

Don't declare an array of values of Base type: object slicing will occur and, moreover, you will lose the virtual calls. 不要声明Base类型的值数组:将发生对象切片 ,此外,您将丢失虚拟调用。

The virtual call is “slower,” but more readable. 虚拟调用“慢”,但更具可读性。 Really, there hardly is any advantage in devirtualizing calls like that. 实际上,像这样的虚拟化调用几乎没有任何优势。 If you're trying to optimize your code, I bet there are better places to look at. 如果您正在尝试优化代码,我打赌有更好的地方可以看。

I will suggest to go with the virtual function way to implement you logic due to following reasons 由于以下原因,我建议采用虚函数方式实现逻辑

(1) I don't know how many cases (case Implementation) you are using but if tomorrow your derived classes extends to more than 50 or even more you will end up writing your cases only , what ever you are trying to do manually by providing the Ids to the derived classes is the job of the compiler which itself inserts the code of initializing the vptr and the VTABLE.best policy is "Not to implement what a compiler can implement by itself" . (1)我不知道你使用了多少案例(案例实施),但如果明天你的派生类扩展到50以上甚至更多,你最终只会写你的案例,你想要手动做什么?将Ids提供给派生类是编译器的工作,编译器本身插入初始化vptr的代码,而VTABLE.best策略是“不实现编译器可以自己实现的”。 So in future no matter how many classes you derive out of base your code will be better,faster and more readable by virtual function way of doing. 因此,将来无论您从基础派生多少个类,您的代码都会通过虚拟函数的方式更好,更快,更易读。

(2) While using the virtual function you have to always always make a function virtual in the base class and access the derived class function(with the same name) by upcasting ( by assigning the derived class object pointer/reference to the base class object).You haven't provided any base class pointer or reference in your implementation, it has to be Base * Arr[100] or Base & Arr[100] (2)在使用虚函数时,您必须始终在基类中创建一个虚函数,并通过向上转换 (通过将派生类对象指针/引用分配给基类对象)来访问派生类函数(具有相同名称)你的实现中没有提供任何基类指针或引用,它必须是Base * Arr [100]或Base&Arr [100]。

What you are doing in 2nd is object slicing, where you are slicing the Base part from the object. 你在第二个做的是对象切片,你正在从对象切割基础部分。

rgds, Softy rgds,Softy

Go for virtual functions. 去寻找虚拟功能。 Period. 期。

I would strongly argue that for cleanliness of code and maintainability that you stick to using virtual functions. 我坚决认为,为了清洁代码和可维护性,你坚持使用虚函数。 There's no real reason to avoid them. 没有理由避免它们。 They are fairly efficient at this point (languages like Java use them by default for all non-static methods). 它们在这一点上相当有效(像Java这样的语言默认使用它们用于所有非静态方法)。 If you actually had code that had to be insanely efficient and you were trying to eke every single last instruction out of it that you could, then you'd need to write both a version with virtual functions and one without and profile it. 如果你真的拥有必须非常高效的代码并且你试图用它来尽可能地完成每条最后一条指令,那么你需要同时编写一个带有虚函数的版本和一个没有的版本并对其进行分析。 Other than that, don't worry about it. 除此之外,不要担心。 You're trying to do what the language itself does without actually using the language's built-in way of doing it, and that's rarely a good idea. 你试图在没有实际使用语言的内置方式的情况下完成语言本身所做的事情,这很少是一个好主意。 It might even be slower - only profiling would tell. 它甚至可能更慢 - 只有剖析才能说明。 Just use virtual functions and don't worry about it. 只需使用虚拟功能,不用担心。

Also, Base Array[255]; 另外, Base Array[255]; is not going to work because all of your objects will get sheared and be only Base objects rather than the derived types. 不会起作用,因为所有对象都会被剪切掉并且只是Base对象而不是派生类型。 You need to use pointers: Base* Array[255]; 你需要使用指针: Base* Array[255]; .

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM