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.
Related
I know that if the class is supposed to be abstract, but does not contain any used-defined method, there is technique to achieve this by making the destructor pure virtual.
class B{
public:
virtual ~B() = 0;
}
As far as I understand the object in example below should not be able to be instantiated.
#include <iostream>
class A{
public:
A(){std::cout<<"A::A()"<<std::endl;}
virtual ~A() = 0;
};
class B : public A{
public:
B(){std::cout<<"B::B()"<<std::endl;}
};
int main(){
B b;
}
I know that pure virtual functions also can have definitions, and that in the case above it should be defined for destructor of B, but something is obscure to me. Is there any particular reason not to make the definition of pure virtual destructor to be implicitly defaulted in C++ standard, because to me it would make a lot of sense.
If a function is declared pure virtual, then this means two things:
The class with such a declaration cannot be instantiated.
Any derived classes must provide a definition for the method, or they also cannot be instantiated.
However, #2 only happens if you don't provide a definition for that pure virtual function declaration. If you do define the pure virtual function, then derived classes do not specifically need to override those methods.
Therefore, if there was always a defaulted definition of a pure virtual destructor, it would be impossible to force a user to declare a destructor for derived classes.
In the vanishingly rare circumstance where you have a class you intend to use as a virtual type, but has no actual interface (I fail to see how you could uphold the Liskov substitution principle when you have no interface) and therefore should not be instantiated, and but you also want a user to not have to define a destructor explicitly, you can do this:
#include <iostream>
class A{
public:
A(){std::cout<<"A::A()"<<std::endl;}
virtual ~A() = 0;
};
A::~A() = default; //Yes, this is legal.
class B : public A{
public:
B(){std::cout<<"B::B()"<<std::endl;}
};
int main(){
B b;
}
However, I highly doubt this circumstance comes up in reality often enough to actually matter. In most real types intended for use in virtual interfaces, they have actual virtual interfaces beyond "can be destroyed". They need virtual destructors, but they also have other virtual functions which can be pure. As such, their destructors don't need to be pure.
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).
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.