开发者

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 Array[255];

Which could contain both Base and it's derivatives. 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.)

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];

And then create the Draw functions in the derivatives:

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. 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:

Base *Array[255];

Otherwise, in C++ (unlike Java), the array could only contain instances of Base and no objects of derived classes. Using a pointer is more like Java's references and allows you to put instances of derived class into the array.


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.

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++.


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

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).


Don’t declare an array of values of Base type: object slicing will occur and, moreover, you will lose the virtual calls.

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.


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). 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]; is not going to work because all of your objects will get sheared and be only Base objects rather than the derived types. You need to use pointers: Base* Array[255];.


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" . 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]

What you are doing in 2nd is object slicing, where you are slicing the Base part from the object.

rgds, Softy

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜