As of C++2a, virtual functions can now be constexpr. But as far as I know, you still cannot call arbitrary function pointers in constexpr context.
Dynamic polymorphism is usually implemented using a vtable, which contains the function pointer to call.
Also, dynamic polymorphism with virtual is useful to call overriding functions of a type you don't know which one it is at compile time. For example:
struct A {
virtual void fn() const {
std::cout << 'A' << std::endl;
}
};
void a_or_b(A const& a) {
// The compiler has no idea `B` exists
// it must be deferred at runtime
a.fn();
}
struct B : A {
void fn() const override {
std::cout << 'A' << std::endl;
}
};
int main() {
// We choose which class is sent
a_or_b(rand() % 2 ? A{} : B{});
}
So considering those that function pointers cannot be called at compile time and virtual polymorphism is used when the compiler don't have enough information to statically infer what function to call, how are virtual constexpr functions possible?
Please keep in mind that constexpr virtual functions would be called at compile time only when the type is already known to the compiler and obviously they would not be called through virtual dispatch.
Corresponding proposal provides similar explanation:
Virtual function calls are currently prohibited in constant
expressions. Since in a constant expression the dynamic type of the
object is required to be known (in order to, for example, diagnose
undefined behavior in casts), the restriction is unnecessary and
artificial. We propose the restriction be removed.
It also has a very nice motivating example.
Related
Motivation, if it helps: : I have struct member functions that are radial-basis-function kernels. They are called 1e06 x 15 x 1e05 times in a numerical simulation. Counting on devirtualization to inline virtual functions is not something I want to do for that many function calls. Also, the structs (RBF kernels) are already used as template parameters of a larger interpolation class.
Minimal working example
I have a function g() that is always the same, and I want to reuse it, so I pack it in the base class.
The function g() calls a function f() that is different in derived classes.
I don't want to use virtual functions to resolve the function names at runtime, because this incurs additional costs (I measured it in my code, it has an effect).
Here is the example:
#include <iostream>
struct A
{
double f() const { return 0; };
void g() const
{
std::cout << f() << std::endl;
}
};
struct B : private A
{
using A::g;
double f() const { return 1; };
};
struct C : private A
{
using A::g;
double f() const { return 2; };
};
int main()
{
B b;
C c;
b.g(); // Outputs 0 instead of 1
c.g(); // Outputs 0 instead of 2
}
I expected the name resolution mechanism to figure out I want to use "A::g()", but then to return to "B" or "C" to resolve the "f()" function. Something along the lines: "when I know a type at compile time, I will try to resolve all names in this type first, and do a name lookup from objects/parents something is missing, then go back to the type I was called from". However, it seems to figure out "A::g()" is used, then it sits in "A" and just picks "A::f()", even though the actual call to "g()" came from "B" and "C".
This can be solved using virtual functions, but I don't understand and would like to know the reasoning behind the name lookup sticking to the parent class when types are known at compile time.
How can I get this to work without virtual functions?
This is a standard task for the CRTP. The base class needs to know what the static type of the object is, and then it just casts itself to that.
template<typename Derived>
struct A
{
void g() const
{
cout << static_cast<Derived const*>(this)->f() << endl;
}
};
struct B : A<B>
{
using A::g;
double f() const { return 1; };
};
Also, responding to a comment you wrote, (which is maybe your real question?),
can you tell me what is the reasoning for the name lookup to stick to the base class, instead of returning to the derived class once it looked up g()?
Because classes are intended to be used for object-oriented programming, not for code reuse. The programmer of A needs to be able to understand what their code is doing, which means subclasses shouldn't be able to arbitrarily override functionality from the base class. That's what virtual is, really: A giving its subclasses permission to override that specific member. Anything that A hasn't opted-in to that for, they should be able to rely on.
Consider in your example: What if the author of B later added an integer member which happened to be called endl? Should that break A? Should B have to care about all the private member names of A? And if the author of A wants to add a member variable, should they be able to do so in a way that doesn't potentially break some subclass? (The answers are "no", "no", and "yes".)
in C++, why compiler does not understand which object is pointed by base class object at compile time?
For ex.
int Add(int nX, int nY)
{
return nX + nY;
}
int Subtract(int nX, int nY)
{
return nX - nY;
}
int main()
{
// Create a function pointer and make it point to the Add function
int (*pFcn)(int, int) = Add;
cout << pFcn(5, 3) << endl; // add 5 + 3
pFcn = Subtract;
cout<< pFcn(5,3)<<endl // pefrom 5-3
return 0;
}
Above code snippet is the example of Late binding or Dynamic binding.
In above example, at compile time only we came to know that 1st Add function is going to call through pFcn & then Subtract function is going to call. Then why it is called to be example of Dynamic binding even though compiler knows which function to call at compile time only?
my question is regarding to virtual function also. consider following ex,
class Base {
public:
void NonVirtual() {
cout << "Base NonVirtual called.\n";
}
virtual void Virtual() {
cout << "Base Virtual called.\n";
}
};
class Derived : public Base {
public:
void NonVirtual() {
cout << "Derived NonVirtual called.\n";
}
void Virtual() {
cout << "Derived Virtual called.\n";
}
};
int main() {
Base* bBase = new Base();
Base* bDerived = new Derived();
bBase->NonVirtual();
bBase->Virtual();
bDerived->NonVirtual();
bDerived->Virtual();
}
Here dynamic binding is happening. Which function to invoked is decided at run-time. So here why compiler can not decide at compile time only which function to invoke?
In the general case, using function pointers requests late binding, but a sufficiently smart compiler could optimize that request and early-bind instead if it can prove that only one function could ever be bound. This is permitted by the as-if optimization rule:
Late binding was requested by the program.
But early binding does not change the observable behavior of the program. Early binding is desirable because it is faster, makes the program smaller, and requires less RAM (pFcn can be removed).
Therefore, early binding may be performed instead.
Consider instead where you might pass function pointers around in a way where the compiler is unable to early-bind, either because it is not smart enough to detect that it is possible, or because it is interacting with code that it cannot observe:
using BinaryIntegerOperator = int (*)(int, int);
int Add(int a, int b) { return a + b; }
int Subtract(int a, int b) { return a - b; }
extern int accumulate(
int initial,
int *first,
std::size_t count,
BinaryIntegerOperator op
);
Now you can pass Add or Subtract as the fourth argument. The called function may not be part of the same binary (perhaps it's part of a dynamically-linked library) and so late binding is inevitable -- accumulate() would have already been compiled by a different compiler.
In cases where the compilation system can prove there is exactly one function that can be called, it is allowed, but not required, to remove the indirect call and to call the function directly. This applies for both function pointers and virtual method dispatch. Generally for virtual methods, the optimization would happen as part of link time optimization where the linker realizes there is only one instance of a given class with a virtual method, or perhaps no classes which ever override a virtual method.
I'm not sure either optimization is considered incredibly important, but I expect both do happen in simple circumstances with the best compilers. (The first example will fall out of fairly standard compiler optimization techniques. Doing it for vtables will almost certainly require a purpose built optimization pass as the compiler has to know how the vtable is and is not modified at runtime.)
Generally that a use of a mechanism simplifies away does not mean one is not using the named mechanism. That is why one might say the function pointer is dynamic binding even though the compiler can prove it does not have interesting dynamic behavior.
Given the updated code above, consider the following:
int main(int argc, char **argv) {
Base* bBase = new Base();
Base* bDerived = new Derived();
// Use test on argc to abstract arbitrary computation.
Base *one_or_the_other = (argc > 1) ? bDerived : bBase;
one_or_the_other->NonVirtual();
one_or_the_other->Virtual();
}
The compiler can no longer determine at compile time which virtual method to call for the second dispatch.
Suppose that situation:
struct base
{
void method()
{
requisites();
do_it();
}
virtual void requisites() const = 0;
void do_it() { /* do it */ }
};
struct derived : base
{
void requisites() const
{
if (!my_requisites)
throw something;
}
}
int main()
{
derived d;
d.method();
return 0;
}
In that case, where I'm not using pointers or references, but directly instances of the derived type, does the compiler need to do a run-time query against the vtable to select the correct override of requisites (the one of derived)? Or is that kind of behaviour as efficent as using no virtual functions? In other words, does the compiler know in compilation time that we are using derived::requisites()?
vtable is not necessarily slower.
For example on x86 in a unix shared object, position independent code has been produced (gcc3, gcc4) using a hack to load ebx with the current eip. This value was used to find a jump table for any static functions. Calling a dynamic function could be performed by querying the this pointer directly, and was faster (if no static functions were called in a given function).
The compiler does know the concrete type, and is able to call directly the function, but may choose to find the function virtually because :-
a) it may be faster.
b) it simplifies the amount of code generation cases.
Let's assume there is a kind of a function, which could be both global function or could be implemented as class member const function (not static, static means global). It depends on user's choice if the function will be called or not called at all. Let say - It is usually not called or called rare - in very special cases.
I am not interested of the program's logic organization. My question is about the memory usage. I know that data member function costs a little bit more (one pointer more), since it is called trough an object. What about the case if the function is not called in runtime?
If it is global function it will be resident in memory during program's lifelong no matter it is called or not. What about the case of data member function, since it is called through and object that is dynamically created, respectively - not created at all, what about the memory needed for the function, where it will be placed and what happens if an object is not created at all?
Thanks.
As was mentioned in the comments, a class member function in C++ can be thought of as a normal C-style function which implicitly takes as an argument a pointer to the instance of the class from which it is called. For example, consider the following C++ code:
class foo {
public:
void set(int j);
private:
int i;
};
void foo::set(int j) {
i = j;
}
The function foo::set can be thought of a C-style function which takes a (hidden) argument of type class foo *, and when you do foo a; a->set(3);, the class foo * that is (implicitly) passed is &a.
In summary, whether or not you ever call foo::set, it will be loaded into memory. (The only possible exception is if there are no calls to the function in your code at all, in which case an optimizer may remove it during compilation, but if it is possible to call it dynamically based on user input then it will be loaded.) On the other hand, no matter how many instances of class foo you have, only one copy of foo::set ever needs to exist in memory.
If your function isn't virtual then there is no overhead of being a member function (aka method).
In fact, in generated object code there is no such notion of a "member function" (unless it's virtual, more on that later). All methods are functions with special variable this. Compiler at the compile time knows what method is to be called at the run time, so it can generate method-specific object code (with some handling of this). By the way, that's the case why the following code doesn't crash:
#include <iostream>
class Crashy {
public:
void wouldItCrash() {
std::cout << "Hey, I'm still alive!" << std::endl;
}
};
int main() {
Crashy* ptr = 0;
ptr->wouldItCrash();
return 0;
}
Despite of null pointer there, programs successively finishes and prints "Hey, I'm still alive!". And that's okay if you think about method wouldItCrash as some kind of a function with special parameter this:
#include <iostream>
void Crashy__wouldItCrash(Crashy *this) {
std::cout << "Hey, I'm still alive!" << std::endl;
}
int main() {
Crashy* ptr = 0;
Crashy__wouldItCrash(ptr);
return 0;
}
We don't dereference the pointer in function, so no problems happen.
Consider the following simple program:
#include <iostream>
void FunctionName__() {
std::cout << "Hello from function!" << std::endl;
}
class ClassName__ {
public:
void MethodName1__() {
std::cout << "Hello from method 1!" << std::endl;
}
void MethodName2__() {
std::cout << "Hello from method 2!" << std::endl;
}
};
int main() {
FunctionName__();
ClassName__ a;
a.MethodName1__();
a.MethodName2__();
return 0;
}
If you compile it without optimizations (just g++ main.cpp) and then look at the symbols table (nm a.out), you'll see
0804876d T _Z14FunctionName__v
...
0804882c W _ZN11ClassName__13MethodName1__Ev
08048858 W _ZN11ClassName__13MethodName2__Ev
That is, all methods became just plain functions with special names (so no conflict could happen, see name mangling)
Virtual functions
As I said earlier, there are some special rules applying to the virtual functions. Virtual functions cannot be resolved at the compile-time (compiler doesn't know which instance of derived class will be processed at the run-time), so it's delayed to the run-time. So in order to serve virtual functions, each class (with that kind of functions, of course) has a special lookup table named virtual method table (aka vtable). In that case you clearly pay some memory space: you need a pointer to the function in the vtable and a pointer to the vtable for each instance of your class.
In typical C++ implementations:
A function is a function, regardless of whether it's a member function of some class, and it will reside in memory "forever" (disregarding demand-paging and all that).
A non-virtual member function is nothing more than an ordinary function that takes a hidden argument called this.
A virtual member function is a member function that has its address recorded in a dispatch table for the class that it belongs to.
So member functions are very much like ordinary functions, the main thing that changes is the way the call is done: with an additional argument, and possibly through a hidden function pointer.
One of my friends asked me "How Runtime Polymorphism is achieved in C++?" I answered "By Inheritance"
He said "No, it can be achieved only using virtual functions".
So I gave him an example of the following code :-
#include<iostream>
using namespace std;
class A
{
public:
int i;
A(){i=100;}
};
class B : public A
{
public:
int j;
B(){i = -1; j = 99;}
};
void func(A& myA)
{
cout<<myA.i << endl;
}
int main()
{
B b;
A* a = new B();
func(*a);
func(b);
delete a;
return 0;
}
Here, function func() takes reference of A but we pass object of B and we can print the value of public member "i". He said it is compile time polymorphism.
My questions are :-
1) Is Runtime polymorphism achieved only with virtual functions?
2) Is the example above has runtime polymorphism or compile time?
3) If I have the following code :-
void func2(A& myA)
{
cout << myA.i << endl;
// dynamic/static cast myA to myB
cout<<myB.j << endl;
}
what kind of polymorphism is it? Or is it even polymorphism?
The example does not show dynamic polymorphism. The method to be called is known at compile time. There is no runtime decision(based on actual object type) as to which method should be called. There is no different behavior for different types.
For the example to be example of dynamic polymorphism.
You need to provide a virtual member function in Base class and overide it in derived class. The actual method to be called is decided by the actual type of the object pointed by the Base class pointer.
Online sample:
#include<iostream>
using namespace std;
class A
{
public:
virtual void doSomething()
{
std::cout<<"\nIn A::doSomething()";
}
};
class B : public A
{
public:
virtual void doSomething()
{
std::cout<<"\nIn B::doSomething()";
}
};
int main()
{
B b;
A obj;
A* a = &b;
a->doSomething();
a = &obj;
a->doSomething();
return 0;
}
Output:
In B::doSomething()
In A::doSomething()
Is Runtime polymorphism acheived only with virutal functions?
No, but virtual functions is the most common and correct way to do so.
Polymorphism can be achieved through function pointers. Consider the following code example, the actual method to call is decided at run-time depending on user input. It is a form of polymorphism through not in strict sense C++ sense which mandates different behaviors for different types.
#include <iostream>
typedef void (*someFunction)(int, char*);
void FirstsomeFunction(int i, char *c)
{
std::cout<<"\n In FirstsomeFunction";
}
void SecondsomeFunction(int i, char *c)
{
std::cout<<"\n In SecondsomeFunction";
}
int main()
{
someFunction arr[1];
int x = 0;
std::cin >> x;
if(x ==0)
arr[0] = &FirstsomeFunction;
else
arr[0] = &SecondsomeFunction;
(arr[0])(10,"Hello");
return 0;
}
Is the example above has runtime polymorphism or compile time?
There is no polymorphism of any kind. The same method will be called in all cases. There is no different behavior for different types and hence it does not classify as polymorphism of any kind.
The C language's fprintf is a polymorphic function.
You can pass it various handles and it can print to a file, stdout, a printer, a socket, anything which the system can represent as a stream.
FILE* file = fopen("output.txt", "w"); // a file
FILE* file = stdout; // standard output
FILE* file = fopen("/dev/usb/lp0", "w"); // a usb printer
FILE* file = popen("/usr/bin/lpr -P PDF", "w"); // a PDF file
FILE* file = fdopen(socket(AF_INET,SOCK_STREAM,0), "r+"); // network socket
fprintf(file, "Hello World.\n");
what you wrote is not polymorphism.
This is how you do polymorphism in C++ :
#include<iostream>
using namespace std;
class A
{
public:
virtual void func(){
cout << "printing A" << endl;
}
virtual ~A(){}
};
class B : public A
{
public:
void func(){
cout << "printing B" << endl;
}
};
int main()
{
A* a = new A();
A* b = new B();
a->func(); // "printing A"
b->func(); // "printing B"
delete a;
delete b;
return 0;
}
If you were to remove the virtual keyword, the method func of A would be called twice.
One of my friends asked me "How Runtime Polymorphism is achieved in C++?" I answered "By Inheritance"
He said "No, it can be achieved only using virtual functions".
First, the term polymorphism is ambiguous: in the general computing science sense it refers to an ability to implicitly invoke type-specific code, whether at compile time or run-time. In the C++ Standard it is defined very narrowly are being virtual dispatch (that's the perogative of standards). Obviously for your friend's question to be meaningful, as he's asking how it's achieved in C++ his perspective must be from outside C++ - in the larger context of Computing Science terminology.
Certainly, virtual functions/dispatch are an answer, but are they the only answer...?
To attempt to answer that, it helps to have a clear conception of what behaviour qualifies as run-time polymorphic. Consider:
void f(X& x)
{
// the only situation where C++ doesn't know the run-time type of a variable is
// where it's an instance of a class/struct accepted by reference or pointer
...some operation involving "x"...
}
Any mechanism that could result in different machine code for the operation being invoked involving "x", where the reason relates specifically to the run-time type of "x", is getting pretty close to run-time polymorphic, but there's one final issue: was that branching decided implicitly by the language, or arranged explicitly by the programmer?
In the case of virtual dispatch, the compiler implicitly knows to create the virtual dispatch tables and lookups that branch to the type-appropriate code.
But, say we have a function pointer that was previously set to address type-appropriate code, or a type-specific number or enum that is used to control a switch to a type-specific case. These functionally achieve the same behaviour as run-time virtual dispatch, but the set up had to be done explicitly by the developer, and there's no compiler enforcement to make sure that the determination is done purely on run-time type. Whether they qualify or not is arguable. Because C++ has a fully implicit mechanism in virtual dispatch, and because in the C++ Standard polymorphism has a narrowed definition related specifically to virtual dispatch, I'd guess that most C++ programmers would say "no".
But in the world of C, describing say qsort or bsearch (two Standard libC functions that handle arbitrary types using run-time dispatch via function pointer arguments) as run-time polymorphic might aid quick understanding... it's more normal to say that they're generic implementations though.
Still, there's doubtless hundreds of Computing Science textbooks out there with functional definitions of run-time polymorphism, and I'd bet dispatch using function pointers or other programmer-initialised metadata satisfied a good percentage of them. So, it's pointless to be too insistent that there's a single unambiguous answer.
My questions are :-
1) Is Runtime polymorphism achieved only with virtual functions?
As above, I'd lean towards "yes" in the context of C++, but it's (endlessly) arguable.
2) Is the example above has runtime polymorphism or compile time?
Neither... there's not even two functions to choose between on the basis of type - you're always running the same machine code for func(): that picked by the compiler given an expectation that the type is A.
3) If I have the following code :-
void func2(A& myA)
{
cout << myA.i << endl;
// dynamic/static cast myA to myB
cout<<myB.j << endl;
}
what kind of polymorphism is it? Or is it even polymorphism?
Not polymorphic at all, as you have no branching based on type. A dynamic cast could consult the compiler-populated type meta-data in the run-time type of myA, and if you used that to only conditionally invoke the access to myB.j - which would be undefined behaviour unless myA was a B - then you're back at manually, explicitly developer coordinated type-specific behaviour, and whether that qualifies as "polymorphism" for you is discussed above.
Polymorphism is achieved with virtual functions. But to have any effect, i.e. different behaviour depending on type, you need inheritance too
struct A {
virtual void f() = 0;
};
struct B : public A {
void f() {
// do B things
std::cout << "B::f() called\n";
}
};
struct C : public A {
void f() {
// do C things
std::cout << "C::f() called\n";
}
};
Now you can have pointers or references to A with different behaviour, depending on whether it's a B or C.
[C++]
Polymorphism is defined as one interface to control access to a general class of actions. There are two types of polymorphism one is compile time polymorphism and the other is run time polymorphism. Compile time polymorphism is functions and operators overloading. Runtime time polymorphism is done using inheritance and virtual functions.
Polymorphism means that functions assume different forms at different times. In case of compile time it is called function overloading. For example, a program can consist of two functions where one can perform integer addition and other can perform addition of floating point numbers but the name of the functions can be same such as add. The function add() is said to be overloaded. Two or more functions can have same name but their parameter list should be different either in terms of parameters or their data types. The functions which differ only in their return types cannot be overloaded. The compiler will select the right function depending on the type of parameters passed. In cases of classes constructors could be overloaded as there can be both initialized and uninitialized objects.