even i think that question is stupid. but i've a little experience.
i have a base class that has such method:
class A{ virtual void func(int)=0 };
and inherited class
class B :public A
{
//how should i write?
//a
virtual void func() { implementation...}
//b
void func() {implementation }
//my target is to redefine a function of ansestor
//i worry that variant b can cover ansestor function and i will not redefine it
//but what if i don't want that the function that was virtual in ansestor, will be virtual in subclass?
i'm confused
}
i don't know that to do. if i don't need this virtual function complete
You ask, "what if i don't want that the function that was virtual in ansestor, will be virtual in subclass?"
Sorry, but every function that is declared virtual in a base class, is also virtual in all derived classes.
It actually doesn't matter whether you use the virtual keyword in the derived-class declaration. Options a and b are identical -- in both cases B::func is virtual.
I suggest your write two small programs, one for each implementation to determine which suits your needs.
In C++ the function signature consists of the function name and function arguments. In a class you cannot have two functions with same signature. So your second (non-virtual) function declaration will generate compiler errors.
In short:
virtual void func() { //implementation}
and
void func() { //implementation }
have the same signature and cannot be declared in the same class.
Virtual means that reimplementation is possible in inherited class(es). Virtual function will allways be virtual no matter the depth of inheritance.
Related
I have a class A and a class B that inherits from A. A has a foo method which I would like to override in B.
class A {
public:
void foo();
...
}
class B: public A {
public:
void foo();
...
}
The solution to this would of course be to define A::foo() as a virtual method, by declaring it as virtual void foo();. But the problem is that I can't do that, since the A class is defined in a third-party library so I would rather not change its code.
After some searching, I found the override keyword (so that the declaration for B::foo would be void foo() override;), but that didn't help me since that's not what override is for, override can apparently only be used on virtual methods to be sure that the method is really overriding another method and that the programmer didn't make a mistake, and it generates an error if the method isn't virtual.
My question is how can I achieve the same effect as making A::foo virtual without changing any of the code for A, but only the code for B?
A bit late. But you can use std::variant and delegate methods to the two classes A and B according to the concrete type.
If your compiler is not that up to date, use a tagged union instead.
The code segment below works fine:
#include <iostream>
#include <string>
using namespace std;
class HelpInterface {
public:
void getHelp();
};
class Applicaiton : public HelpInterface {
public:
void getHelp() {
cout << "General help";
}
};
int main(void) {
Applicaiton applicaiton;
applicaiton.getHelp();
}
Make the getHelp function virtual in HelpInterface class and I will get a linker error:
class HelpInterface {
public:
virtual void getHelp();
};
If I make an empty implemenation of getHelp as below things will work again:
class HelpInterface {
public:
virtual void getHelp() {};
};
Can someone please help me understand why virtual throws a linker error unless I have an implementation for getHelp in the base class and why a non-virtual function with no implementation works just fine? In this example, the base function never gets called.
Here is a screenshot of VS2013 with the linker error:
If you want your base class method to be virtual and provide no implementation, you must set it equal to zero like this:
class HelpInterface {
public:
virtual void getHelp() = 0;
};
This is known as a pure virtual method. It has the effect of making your class abstract and forcing all of its derived classes to provide an implementation of the method. Consequently, take note that you will no longer be able to create an instance of the base class because it is abstract.
When a method is in the base class but isn't virtual the linker will not actually reference the implementation of the method if you don't have an explicit call to that method on either a pointer/reference to the base type (On an instance of the derived class) or an instance of the base type.
Virtual functions can be implemented a number of different ways, and are implementation specific. One of the most common is by using a virtual table. (Also known by virtual method table, virtual function table, virtual call table, dispatch table, vtable, or vftable), and I'm pretty sure your compiler (VS2013) uses this method of implementing virtual functions.
A virtual table is a table of function pointers for the virtual member functions. The class instance would contain a pointer to the table that the class belongs to.
When you make a function virtual the linker tries to put it into the virtual table for that type. It doesn't matter whether you call it or not or instantiate a base class (also an implementation specific detail).
As qexyn has already answered, to get around that you declare the method as pure virtual by adding = 0 after the virtual function declaration. This tells the linker to put a null pointer in the virtual function table for the class. You can also declare the virtual function pure virtual and also provide an implementation. This forces the derived classes to implement that function, but allows them to choose to use the default method.
The reason for this is that your base class definition is using indirection to get the actual function for Application.
This is often implemented with a function pointer, but in any case there could be a derived class that doesn't override the base class implementation.
Although this isn't usually reproducible that is simply because member functions are implicitly declared inline and when the implementation is visible an optimizing compiler will do exactly that; inline the function. The proof is in the optimization.
What you want, is to make sure that every derived class from your base implements getHelp(). This is a common idiom and is a core language feature. You want a "pure virtual function". This will make your base class an "abstract base class" which is actually a synonym for "interface" in object-oriented jibber-jabber.
The way to do this in C++ is with a special member-function specific syntax after all of the member function qualifiers (I'm using trailing return types here cause I think they're pretty):
class base{
public:
virtual auto func() -> void = 0;
};
This specifies that base is an abstract base class with a pure virtual function func() that all classes derived from it will implement.
In your case you would write:
class HelperInterface{
public:
virtual void getHelp() = 0; // probably want const qualifier
};
And just leave Application as it is.
You learn something every day, huh?
Here is a very basic example:
class Base {
public:
virtual void sayHi() const {}
virtual void sayHello() {}
virtual ~Base(){}
};
class Derived : public Base {
public:
virtual void sayHi() {}
virtual void sayHello() const {}
};
int main()
{
Base *b = new Base();
Base *d = new Derived();
return 0;
}
The Base's vptr, in 'b' has virtual functions of Base class. The derived class object 'd' however, on inspection, list virtual functions of only base.
The question here is not, why are the functions not being overridden so the use of override keyword isn't required here. The question is, why doesn't a particular class's VTable contain its own virtual functions? In this case why vtable of 'd' doesnt contain D::sayHi and D::sayHello?
I am open to downvotes, but be brave to mention and tell the reason.
edit:
I know that the CONSTness might look wrong here, but the question is not about overriding.
This is specifically tried out in VS2012 Update4
Here you have different function overloads that do not override the defined virtual functions:
virtual void sayHi() const {}
virtual void sayHello() {}
void sayHi() {} // non virtual function with a different signature (no const)
void sayHello() const {} // non virtual function with a different signatuere (const)
If you want to avoid such subtle errors, use the keyword override : if the function that you think overrides a virtual function of the base class has a different signature or doesn't even exist (e.g.typo...) the compiler will generate an error.
Edit following your edit:
I see that you've updated the code to make the overloaded non overriding functions virtual as well.
Now the vtable of the derived function contains four distinct functions. However, through the base pointer you can only access the virtual functions defined in the base. This is why the MSVC debugger shows you only 2:
By the way, the debugger seems to always show the vtable as a member of the Base. But if you look at the assembler generated, you'll see the mangled names of all the virtual functions of the derived class in its vtable:
Your Hi function does not override the base class Hi function as their const specifiers are wrong.
The same is true for your Hello functions, albeit the other way round.
If you use C++11 or later you can use the override keyword to make sure this doesn't happen.
It was already mentioned that you are not overriding the functions as you are changing the functions signature by adding a const.
Concerning your actual questions:
It will use the vtable-pointer from the base class to point to its own vtable that has different entries. Thats just how it works. It "looks" like the base class but behaves "different". Thats polymorphic behaviour in C++.
If each deriving class would add its own vtable, a lot of things would be broken in C++. Multiple vtable pointers will only be part of an instance of a class, which derives from multiple classes containing virtual functions or when using virtual inheritance.
Pure virtual functions are a must-have property for abstract base classes. So no implementations should be made, which is very intuitive to understand. But Recently I came to know that pure virtual functions can still be defined later and be invoked statically(not by object instances). I can't think up a reason for this. If one virtual function is defined as pure, then what's the reason to implement it?
class A{
public:
...
virtual void interface() = 0; //Pure Virtual functions
...
}
void A::interface() //Implementation
{
cout<<"This the implementation for A interface";
}
I am curious about the logic behind this. Why is c++ designed like this way?
It might make sense to have a "default" implementation, which concrete classes can use if it's useful to them. They still need to override it, but can call the base-class version non-virtually:
struct B : A {
void interface() {
A::interface(); // call the default implementation
// and maybe do some B-specific things too
}
};
I can't think up a reason for this. If one virtual function is defined as pure, then what's the reason to implement it?
The purpose of a pure virtual function is not to prohibit definitions. It is to mark the class as uninstantiable.
Providing a definition may be useful for deriving classes:
struct A
{
virtual void foo() = 0;
};
void A::foo()
{
/* some common logic here */
}
struct B : A
{
virtual void foo() overrides
{
bar();
A::foo();
}
void bar();
};
struct C : A
{
virtual void foo() overrides
{
baz();
A::foo();
}
void baz();
};
A pure virtual function simply means that the function must be overidden by all derived classes it does not mean that the function cannot/should not have a implementation of its own. Two most obvious cases for such a pure virtual function having implementation are:
A Derived class implementation can call Base class implementation
Sometimes you would want a base class to be made abstract but there is no method which you can mark as pure virtual in such a case a destructor is most obvious choice but in such a destructor still needs a implementation.
interface() = 0 means derived classes must provide an implementation, so the definition effects derived classes, but the base class is permitted to have an implementation of the method so that derived classes can always call base::interface().
You apparently completely misunderstood the meaning of the term "statically" in this context.
Yes, pure virtual functions can still have bodies, i.e. they can still be defined.
And no, you cannot invoke such function "without an object instance", as you seem to incorrectly believe. A pure virtual function with a body is still a non-static member function. It still requires an object instance to be invoked.
When someone says that such function can be invoked "statically", it means that it can be called directly, without using virtual dispatch mechanism. Function calls that go through virtual dispatch are sometimes called "virtual calls" or "dynamic calls", while direct function calls are sometimes called "static calls". The term "static" in this context assumes a completely different meaning, not connected in any way to static member functions.
In C++ language a direct non-virtual (i.e. "static") call can be performed explicitly by specifying a qualified member name in the call. For example, if class B derives from your class A, then inside some method B::foo() you can use the following syntax
void B::foo() {
A::interface(); // <- qualified method name
}
which performs a direct call to the implementation of A::interface() you provided. For an object b of type B the same kind of call can be performed as
B b;
b.A::interface(); // <- qualified method name
In both cases the call is performed for a specific object (*this in the first example, and b in the second).
Pretty much the same thing happens implicitly when destructors of derived classes call destructors of base class, which is why you will often encounter this situation with pure virtual destructors (i.e. they are declared as pure virtual, yet have a body).
In C++, when a method is declared, I've noticed that sometime the method may have an assignement appended to it.
Could anyone tell me what this is?
For example:
virtual void MyMethod () = 0;
What doe the '= 0' mean. :)
Thanks everyone !!!
It means it's a pure virtual function, i.e. no actual definition of it is available in this class and it must be overridden in a subclass. It's not actually an assignment as such, zero is the only value you can "assign".
And this is C++ syntax; in C# the same would be accomplished with the abstract keyword.
In C++ this means that the method is a pure virtual method.
This means that an instance of this particular class-type cannot be instantiated. You can only create instances of classes derived from this, which override all pure virtual methods in the base class.
A base class with pure virtual methods defines an interface that derived classes have to implement, and is not meant to be used on its own.
Contrary to what calmh claims, as far as I know pure virtual functions can be implemented and they can be called explicitly.
#include <cstdio>
class A
{
public:
virtual void foo() const = 0; //pure virtual
};
void A::foo() const { puts("A::foo"); }
class B: public A
{
public:
virtual void foo() const { puts("B::foo"); }
};
int main()
{
//A a; //this would be an error - main point of having pure virtual functions
B b;
b.foo();
b.A::foo();
}
Usually one wouldn't do this, though, except perhaps if the virtual destructor is pure in a base class (in this case it has to be defined).
In C#, that is a syntax error.
If you meant C++, see calmh's answer.