English 中文(简体)
C++ : implications of making a method virtual
原标题:

Should be a newbie question...

I have existing code in an existing class, A, that I want to extend in order to override an existing method, A::f().

So now I want to create class B to override f(), since I don t want to just change A::f() because other code depends on it.

To do this, I need to change A::f() to a virtual method, I believe.

My question is besides allowing a method to be dynamically invoked (to use B s implementation and not A s) are there any other implications to making a method virtual? Am I breaking some kind of good programming practice? Will this affect any other code trying to use A::f()?

Please let me know.

Thanks, jbu

edit: my question was more along the lines of is there anything wrong with making someone else s method virtual? even though you re not changing someone else s implementation, you re still having to go into someone s existing code and make changes to the declaration.

问题回答

If you make the function virtual inside of the base class, anything that derives from it will also have it virtual.

Once virtual, if you create an instance of A, then it will still call A::f.

If you create an instance of B and store it in a pointer of type A*. And then you call A*::->f, then it will call B s B::f.

As for side effects, there probably won t be any side effects, other than a slight (unnoticeable) performance loss.

There is a very small side effect as well, there could be a class C that also derives from A, and it may implement C::f, and expect that if A*::->f was called, then it expects A::f to be called. But this is not very common.

But more than likely, if C exists, then it does not implement C::f at all, and in which case everything is fine.


Be careful though, if you are using an already compiled library and you are modifying it s header files, what you are expecting to work probably will not. You will need to recompile the header and source files.

You could consider doing the following to avoid side effects:

  1. Create a type A2 that derives from A and make it s f virtual
    • Use pointers of type A2 instead of A
    • Derive B from type A2.
    • In this way anything that used A will work in the same way guaranteed

Depending on what you need you may also be able to use a has-a relationship instead of a is-a.

There is a small implied performance penalty of a vtable lookup every time a virtual function is called. If it were not virtual, function calls are direct, since the code location is known at compile time. Wheras at runtime, a virtual function address must be referenced from the vtable of the object you re calling upon.

To do this, I need to change A::f() to a virtual method, I believe.

Nope, you do not need to change it to a virtual method in order to override it. However, if you are using polymorphism you need to, i.e. if you have a lot of different classes deriving from A but stored as pointers to A.

There s also a memory overhead for virtual functions because of the vtable (apart from what spoulson mentioned)

There are other ways of accomplishing your goal. Does it make sense for B to be an A? For example, it makes sense for a Cat to be an Animal, but not for a Cat to be a Dog. Perhaps both A and B should derive from a base class, if they are related.

Is there just common functionality you can factor out? It sounds to me like you ll never be using these classes polymorphically, and just want the functionality. I would suggest you take that common functionality out and then make your two separate classes.

As for cost, if you re using A ad B directly, the compile will by-pass any virtual dispatching and just go straight to the functions calls, as if they were never virtual. If you pass a B into a place expecting `A1 (as a reference or pointer), then it will have to dispatch.

There are 2 performance hits when speaking about virtual methods.

  • vtable dispatching, its nothing to really worry about
  • virtual functions are never inlined, this can be much worse than the previous one, function inlining is something that can really speed things in some situations, it can never happen with a virtual function.

How kosher it is to change somebody else s code depends entirely on the local mores and customs. It isn t something we can answer for you.

The next question is whether the class was designed to be inherited from. In many cases, classes are not, and changing them to be useful base classes, without changing other aspects, can be tricky. A non-base class is likely to have everything private except the public functions, so if you need to access more of the internals in B you ll have to make more modifications to A.

If you re going to use class B instead of class A, then you can just override the function without making it virtual. If you re going to create objects of class B and refer to them as pointers to A, then you do need to make f() virtual. You also should make the destructor virtual.

It is good programming practise to use virtual methods where they are deserved. Virtual methods have many implications as to how sensible your C++ Class is.

Without virtual functions you cannot create interfaces in C++. A interface is a class with all undefined virtual functions.

However sometimes using virtual methods is not good. It doesn t always make sense to use a virtual methods to change the functionality of an object, since it implies sub-classing. Often you can just change the functionality using function objects or function pointers.

As mentioned a virtual function creates a table which a running program will reference to check what function to use.

C++ has many gotchas which is why one needs to be very aware of what they want to do and what the best way of doing it is. There aren t as many ways of doing something as it seems when compared to runtime dynamic OO programming languages such as Java or C#. Some ways will be either outright wrong, or will eventually lead to undefined behavior as your code evolves.

Since you have asked a very good question :D, I suggest you buy Scott Myer s Book: Effective C++, and Bjarne Stroustrup s book: The C++ Programming Language. These will teach you the subtleties of OO in C++ particularly when to use what feature.

If thats the first virtual method the class is going to have, you re making it no longer a POD. This can break things, although the chances for that are slim.

POD: http://en.wikipedia.org/wiki/Plain_old_data_structures





相关问题
Undefined reference

I m getting this linker error. I know a way around it, but it s bugging me because another part of the project s linking fine and it s designed almost identically. First, I have namespace LCD. Then I ...

C++ Equivalent of Tidy

Is there an equivalent to tidy for HTML code for C++? I have searched on the internet, but I find nothing but C++ wrappers for tidy, etc... I think the keyword tidy is what has me hung up. I am ...

Template Classes in C++ ... a required skill set?

I m new to C++ and am wondering how much time I should invest in learning how to implement template classes. Are they widely used in industry, or is this something I should move through quickly?

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

typedef ing STL wstring

Why is it when i do the following i get errors when relating to with wchar_t? namespace Foo { typedef std::wstring String; } Now i declare all my strings as Foo::String through out the program, ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

Window iconification status via Xlib

Is it possible to check with the means of pure X11/Xlib only whether the given window is iconified/minimized, and, if it is, how?

热门标签