I would expect that if foo is declared in class D, but not marked virtual, then the following code would call the implementation of foo in D (regardless of the dynamic type of d).
D& d = ...;
d.foo();
However, in the following program, that is not the case. Can anyone explain this? Is a method automatically virtual if it overrides a virtual function?
#include <iostream>
using namespace std;
class C {
public:
virtual void foo() { cout << "C" << endl; }
};
class D : public C {
public:
void foo() { cout << "D" << endl; }
};
class E : public D {
public:
void foo() { cout << "E" << endl; }
};
int main(int argc, char **argv)
{
E& e = *new E;
D& d = *static_cast<D*>(&e);
d.foo();
return 0;
}
The output of the above program is:
E
Standard 10.3.2 (class.virtual) says:
If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or indirectly from Base, a member function vf with the same name and same parameter list as Base::vf is declared, then Derived::vf is also virtual (whether or not it is so declared) and it overrides*
[Footnote: A function with the same name but a different parameter list (clause over) as a virtual function is not necessarily virtual and does not override. The use of the virtual specifier in the declaration of an overriding function is legal but redundant (has empty semantics). Access control (clause class.access) is not considered in determining overriding. --- end foonote]
Quick answer may be no, but correct answer is yes
C++ doesn't know about function hiding, so overriding virtual function without virtual keyword marks that function virtual too.
You are not creating any copy of the object of e and putting it in d. So d.foo() follows normal polymorphic behavior and calls derived class method. A method which is declared as virtual in the base class becomes automatically virtual in the derived class also.
The output ("E") behaves exactly as one would expect it to behave.
The reason:
The dynamic (i.e. runtime) type of that reference is E. You are doing a static upcast to D, but that does not change the actual type of the object of course.
That's the very idea behind virtual methods and dynamic dispatches: You see the behavior of the type you were instantiating, which is E, in this case.
Related
This question already has an answer here:
method in the derived class got executed without a *virtual* keyword in the referred class
(1 answer)
Closed 2 years ago.
Probably, i misunderstood c++ polymorphism(virtual function).
Please point me what i miss.
the source code is below
#include <iostream>
using namespace std;
class A {
public:
virtual void print(void) {
cout<<"class A"<<endl;
}
};
class B : public A {
public:
void print(void) {
cout<<"class B"<<endl;
}
};
class C : public B {
public:
void print(void) {
cout<<"class C"<<endl;
}
};
int main() {
A a;
B b;
C c;
A *pAa = &a;
A *pAb = &b;
A *pAc = &c;
B *pBc = &c;
pAa->print();
pAb->print();
pAc->print();
pBc->print(); // shouldn't be "class B"
return 0;
}
result
------------------------------
class A
class B
class C
class C // shouldn't be "class B"
my understanding is that
the last print statement should print "class B"
because pBc is a pointer of class B and the print function in class B is non virtual member function. i could not find the answer about this situation.
please tell me why or point me where i can find the answer and
understand c++ polymorphism in comprehension.
thanks.
If a function with a given signature is declared as virtual in a top-level base class, then the function is virtual in all derived classes no matter if it is marked with the keyword virtual (override, final) or not:
virtual function specifier
Then this function in the class Derived is also virtual (whether or not the keyword virtual is used in its declaration)
struct Base {
// Pure virtual function.
virtual void foo() const = 0;
};
struct A : public Base {
// Overriding virtual function, even if it
// is not marked as virtual (override, or final).
void foo() const {}
};
In A, adding the virtual specifier to foo() would only bring semantic value; it will be no functional difference whether virtual is omitted or not (unless someone changes the interface in Base).
Many static analyzers enforce(1) marking derived virtual functions with override or final, for two reasons:
semantics; clearly showing the given function is a virtual function (as per being defined so higher up in the inheritance chain), and
enforcement; if a function is marked as override and final but is not actually an overriding function, you will get a compiler error, which can be particularly useful to protect against mistakes when changing a base class interface (whilst forgetting which classes that actually implements this interface).
E.g.:
struct Base {
// Pure virtual function.
virtual void foo() const = 0;
};
struct A : public Base {
// Overriding virtual function.
void foo() const override {}
};
struct B final : public Base {
// Overriding (final) virtual function.
void foo() const final {}
// Error: Function does not override.
// void bar() const override {}
};
(1) E.g. Rule A10-3-1 in the Autsar C++14 Language Guidelines (safety-critical development in automotive) is categorized as a required rule: Virtual function declaration shall contain exactly one of the three specifiers:(1) virtual, (2) override, (3) final.
the print function in class B is non virtual member function
No. Since A::print is marked as virtual and B inherits from A, then B::print is virtual too; regardless of the keywork virtual is specified on it or not.
(emphasis mine)
If some member function vf is declared as virtual in a class Base, and
some class Derived, which is derived, directly or indirectly, from
Base, has a declaration for member function with the same
name
parameter type list (but not the return type)
cv-qualifiers
ref-qualifiers
Then this function in the class Derived is also virtual (whether or not the keyword virtual is used in its declaration) and overrides Base::vf (whether or not the word override is used in its declaration).
I'm sure that someone has asked this question before but I simply don't know what to search for. So I'm happy to remove this question as soon as someone points me to a similar one. I'm also happy to rename the questions if someone has a better suggestion :-)
I want to know if the following code is defined behavior by the standard or if this might be compiler/platform dependent:
struct A
{
virtual void f()
{
std::cout << "A::f()" << std::endl;
}
};
struct B : public A
{
// f() is not implemented here
};
struct C : public B
{
virtual void f() override
{
B::f(); // call f() of direct base class although it is not implemented there
std::cout << "C::f()" << std::endl;
}
};
int main()
{
A* pA = new C();
pA->f();
}
The output with Visual Studio 2017 and gcc 5.4.0 is:
A::f()
C::f()
Is it true that the compiler will search upwards in the hierarchy until it finds an implementation? Can you link to the C++ standard? I've tested it by making f() in A pure virtual and the linker nicely tells me that there is an unresolved symbol. Can I rely on that?
As I understand it using the scope operator like B::f() always calls the non-virtual version. So there is no polymorphism happening ever, is it?
Edit: The print statements where misleading, replaced "B::f()" with "C::f()".
The dynamic type of the pointer
A* pA = new C();
is C *.
So the virtual function in the class C is called
struct C : public B
{
virtual void f() override
{
B::f(); // call f() of direct base class although it is not implemented there
std::cout << "B::f()" << std::endl;
}
};
The class B does not redefine the virtual function of the base class A. So in this statement
B::f(); // call f() of direct base class although it is not implemented there
the virtual function defined in the class A is called. That is the table of pointers to virtual functions of the class B contains the address of the function defined in the class A.
In this call
B::f();
there is access to the table of virtual functions of the class B and this table contains the address of the function definition in the class A because the function was not overriden in the class B.
From the C++ STandard (5.2.2 Function call)
...If the selected function is non-virtual, or if the id-expression in the class member access expression is a qualified-id, that function
is called. Otherwise, its final overrider (10.3) in the dynamic type
of the object expression is called; such a call is referred to as a
virtual function call. [
I've read about virtual functions in C++ and understood how they provide the programmer with access to the member function of derived class using a pointer of base class. (aka Polymorphism).
The questions that have been bothering me are:
Why declare a function with a same name in the base class, if in the end it has to be declared virtual? (Note: I need answers with respect to the polymorphism aspect of virtual functions)
In the code below, if 'virtual display()' is called with a base class pointer (Line 22), it shows an error. Why are virtual functions in C++ so rigid w.r.t. not getting called by base class pointers?
.
#include <iostream>
using namespace std;
class B
{
public:
void virtual display()
{ cout<<"Inside base class.\n"; }
};
class D : public B
{
public:
void display()
{ cout<<"Inside derived class.\n"; }
};
int main()
{
B *b;
D d;
//Line-22 b->display(); Why can't 'b' call it's own display()?
b = &d;
b->display();
system("pause");
return 0;
}
Output:
Inside derived class.
b is a pointer not an object. Initially it didn't point to anything (so indirecting through it is an error); after b = &d, it points to a D object, so using it to call a virtual function will call D's override.
The virtual dispatch mechanism is defined so that the function is chosen based on the type of the actual object that the pointer points to, not the declared type of the pointer. So if it pointed to a B object then it would call B::display; here, it points to a D object, so it calls D::display.
Why declare a function with a same name in the base class, if in the end it has to be declared virtual?
It needs to be declared in the base class so that, when using a pointer to the base class, the compiler knows that it exists. Whether calling the function through the pointer will call the base-class version, or a version overridden by a derived class, depends on the type of the object.
In the code below, if virtual display() is called with a base class pointer (Line 22), it shows an error.
That's because it doesn't point to anything, so using it is an error. If it were to point to a B object, then it would call the function declared in B.
B b_obj;
b = &b_obj;
b->display(); // "Inside base class"
Why are virtual functions in C++ so rigid w.r.t. not getting called by base class pointers?
They're not; that's the usual way of calling them. But the pointer must point to a valid object for virtual dispatch to work.
I confess I don't quite understand your question #1. Declaring a virtual function in a base class allows derived classes to override that implementation.
There are tons of uses for this (just search for polymorphism, Liskov substitution etc.). As a simple (and contrived) example, consider this:
struct File
{
virtual void open() { some_code; }
virtual void close() { some_code; }
static std::unique_ptr<File> create();
};
struct DbgFile : File
{
virtual void open() { std::clog << "Opening"; File::open(); }
virtual void open() { std::clog << "Closing"; File::close(); }
};
std::unique_ptr<File> File::create()
{
#ifdef NDEBUG
return { new File };
#else
return { new DbgFile };
#endif
}
int main()
{
auto f = File::create();
f->open();
f->close();
}
The above main() uses the File interface, but in debug builds, it will actually work with an object of type DbgFile which logs all operations happening on it.
As to your question #2, the problem in your code is that b doesn't point anywhere. If you do this instead, it will work just fine:
int main()
{
B *b;
B bb;
D d;
b = &bb;
b->display(); // Outputs "Inside base class."
b = &d;
b->display(); // Outputs "Inside derived class."
// In addition, you can explicitly suppress dynamic dispatch:
b->B::display(); // Outputs "Inside base class."
return 0;
}
Why declare a function with a same name in the base class, if in the end it has to be declared virtual? (Note: I need answers with respect to the polymorphism aspect of virtual functions)
It's necessary because,base class has to know which function definition it needs to call at runtime. Its a kind of interface.
In the code below, if 'virtual display()' is called with a base class pointer (Line 22), it shows an error. Why are virtual functions in C++ so rigid w.r.t. not getting called by base class pointers?
Since the pointer is not initialized its throwing an error. Use like below.
Base baseObj1,*basePtr;
basePtr= &baseObj1;
basePtr->Display(); //Inside base class
Having
#include <iostream>
using namespace std;
class A {
public:
virtual void foo() {
cout << "A" << endl;
}
};
class B : public A {
public:
void foo() {
cout << "B" << endl;
}
};
class C : public B {
public:
void foo() {
cout << "C" << endl;
}
};
int main() {
C c;
B* b = &c;
b->foo();
return 0;
}
The output is C, but I expected B.
I didn't declare B::foo() with the virtual modifier, so I expect the function call to be determined by the static type (no polymorphism).
Why is C::foo() being called?
Is it possible to provide a non-virtual function in a derived class, that hides the virtual function in the base? What signature should the derived member function have so that b->foo() calls it, and not (b->*&A::foo)()
The principle of virtual inheritance of a member function is is a direct consequence of the C++ Standard:
10.3/2: If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or indirectly from Base,
a member function vf with the same name, parameter-type-list ,
cv-qualification, and refqualifier (or absence of same) as Base::vf is
declared, then Derived::vf is also virtual.
So regardless of the level of inheritance, the function will be virtual in all the classes derived somehow from A. There is no need to put the keyword virtual.
The goal of this polymorphic approach is to ensure that you always call the appropriate function corresponding to the real idendity of your object, regardless the fact that you use a pointer to a base or a pointer to the real class of the object. This is why you obtain "C" !
In this related SO question I explain a trick to give the impression of removing virtuality at one single level, using multiple inheritance. However it can be done only for a single level (you should do it for the class of your base pointer).
*By the way, you could write pb->B::foo(); no need of *&.
I would expect that if foo is declared in class D, but not marked virtual, then the following code would call the implementation of foo in D (regardless of the dynamic type of d).
D& d = ...;
d.foo();
However, in the following program, that is not the case. Can anyone explain this? Is a method automatically virtual if it overrides a virtual function?
#include <iostream>
using namespace std;
class C {
public:
virtual void foo() { cout << "C" << endl; }
};
class D : public C {
public:
void foo() { cout << "D" << endl; }
};
class E : public D {
public:
void foo() { cout << "E" << endl; }
};
int main(int argc, char **argv)
{
E& e = *new E;
D& d = *static_cast<D*>(&e);
d.foo();
return 0;
}
The output of the above program is:
E
Standard 10.3.2 (class.virtual) says:
If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or indirectly from Base, a member function vf with the same name and same parameter list as Base::vf is declared, then Derived::vf is also virtual (whether or not it is so declared) and it overrides*
[Footnote: A function with the same name but a different parameter list (clause over) as a virtual function is not necessarily virtual and does not override. The use of the virtual specifier in the declaration of an overriding function is legal but redundant (has empty semantics). Access control (clause class.access) is not considered in determining overriding. --- end foonote]
Quick answer may be no, but correct answer is yes
C++ doesn't know about function hiding, so overriding virtual function without virtual keyword marks that function virtual too.
You are not creating any copy of the object of e and putting it in d. So d.foo() follows normal polymorphic behavior and calls derived class method. A method which is declared as virtual in the base class becomes automatically virtual in the derived class also.
The output ("E") behaves exactly as one would expect it to behave.
The reason:
The dynamic (i.e. runtime) type of that reference is E. You are doing a static upcast to D, but that does not change the actual type of the object of course.
That's the very idea behind virtual methods and dynamic dispatches: You see the behavior of the type you were instantiating, which is E, in this case.