I am trying to understand a point here in C++.
If class A has a non-virtual method, and class B, which extends A, overrides that method, can i create an instance of B and somehow use the method defined in B?
Is there a point to override a non-virtual method?
Is there a point to override a non-virtual method?
You are not actually overriding, but this is the behavior, i.e
B* b = new B();
A* a = new B();
b->method(); //Calls B's method
a->method(); // Calls A's method
So, the pointer/reference type determines the method called.
can i create an instance of B and somehow use the method defined in B?
Yes. The pointer/reference type has to be of type B. (see previous example).
If you don't declare method to be virtual, you cannot override it, but you can hide it.
If B inherits from A, and redefines a method defined in A, then new instances of B will call B's version. However, if the method is not virtual, then there is no polymorphic behavior, so if an instance of B is referenced as an A, then the method will be A's. For example:
struct A {
void foo () { std::cout << "A::foo" << std::endl; }
};
struct B : public A {
void foo () { std::cout << "B::foo" << std::endl; }
};
B b;
b.foo();
A *a = &b;
a->foo();
The output of the code above would be:
B::foo
A::foo
However, if the foo method had been virtual, then B::foo would have been printed twice.
If a function is not virtual then the type of the variable determines which implementation is dispatched too:
#include <iostream>
using namespace std;
struct A {
void f() { cout << "A" << endl; }
};
struct B : public A {
void f() { cout << "B" << endl; }
};
int main(int args, char** argv) {
B b;
A& a = b;
b.f();
a.f();
return 0;
}
No, there is no mechanism to override a non-virtual method in class A.
Yes, you can use a non-virtual method from class A overloaded in B by using scope resolution operator A::methodName
Related
I have a base class A and hope to create a class B with very similar functionality. I want class B to have a function to call class A's func1(), but when calling it, the func2() is replaced/over-rided by class B's func2(). My goal is to avoid repeated code and not modify class A. The inheritance implementation below does not work. Should I use inheritance here? How can I achieve my goal?
#include <iostream>
using namespace std;
class A {
public:
void func1() {
func2();
cout << "class A fun1" << endl;
}
private:
void func2() {
cout << "class A fun2" << endl;
}
};
class B : A{
public:
void func3() {
func1();
cout << "class B fun3" << endl;
}
private:
void func2() {
cout << "class B fun2" << endl;
}
};
int main() {
B b;
b.func3();
return 0;
}
The current output is:
class A fun2
class A fun1
class B fun3
But what I want is:
class B fun2
class A fun1
class B fun3
You should use virtual function for that. When a function is declared as virtual, the compiler only uses the implementation of the virtual function that is present in the derived class.
The function in the base class cannot be used directly from the base class. As in, if you create an object for the class A, you won’t be able to call func2() if it’s declared as virtual.
Note: You'll be able to call the virtual function from the derived class even though the virtual function definition is not present in the derived class (because it'll anyways be inherited and you'll be calling the inherited copy of the virtual function).
Hope it helps. Happy coding! :)
#include <iostream>
using namespace std;
class A {
public:
virtual void f() = 0;
};
class B : public A {
public:
void f() {cout << "hi" << endl;}
void g() { cout << "bye" << endl; }
};
int main() {
B b;
A &a = b;
a.f(); // prints "hi"
a.g(); // compile error no member g()
return 0;
}
why does a.g() give compile error while a.f() calls B's f()?
At A &a = b; does the compiler somehow set a boundary of where a's aliasing memory ends?
You are attempting to call g() from an instance of A. A does not have an implementation of g(), so it cannot be called through an A object. The fact that a is a reference to a B does not give a access to any functions that A does not know about.
B, on the other hand is-a A, and defines an implementation of the virtual function f(), so the reference a invokes the correct function.
#include<iostream>
class A {
public:
void init(){
std::cout << "A" << std::endl;
}
};
class B: public A {
public:
void init(){
std::cout << "B" << std::endl;
}
};
int main() {
A *o = new B();
/*
Some codes here
*/
o->init();
return 0;
}
Result:
A
In the above program, the init called is of class A. How do I call the init function of class B?
edit: I need to call both the inits. I can't change the A and B class. And I have to make the object declaration like that in main.
Make the init() function virtual in Class A.
class A {
public:
virtual void init(){
std::cout << "A" << std::endl;
}
};
The object o has two parts. The base part and the derived part. If you want B::init() to be called from o, then you will have to tell the compiler that it is a virtual function and it should look for the function overload in the derived class.
I suggest you go through the tutorial on this website to learn more about inheritance:
http://www.learncpp.com/cpp-tutorial/113-order-of-construction-of-derived-classes/
You have some options here:
B *o = new B(); // in Main
or
(B *)o->init(); // in Main
or
virtual void init(){
std::cout << "A" << std::endl;
} // in Class A
b = dynamic_cast<B*>(o);
if(b!=NULL)
b->init();
this will call the function for object of type B.
make init function virtual
create a pointer of class A
create an object of class B
assign address of B object to pointer A
now access init function of B
since class B hides the definition of init() in its base-class, it will make the function sensitive to the type of any pointer or reference from which the function might be called.
And as you mentioned A and B are prewritten class, you can instantiate a pointer to class B, or cast to a pointer to class B.
What's the difference between redefining and using a virtual function? Don't they serve the same purpose? You are allowing objects of a derived class to call their own versions of a function by the same name in both cases..so where is the distinction?
An example says it best:
#include <iostream>
using namespace std;
class A {
public:
virtual void f1() { cout << "Class A" << endl; }
void f2() { cout << "Class A" << endl; }
virtual ~A(){}
};
class B : public A {
public:
virtual void f1() { cout << "Class B" << endl; }
void f2() { cout << "Class B" << endl; }
virtual ~B(){}
};
int main()
{
A *a = new B;
a->f1();
a->f2();
}
...
$ ./override
Class B
Class A
You can see that when we reference the instance of B, f1() still calls B's version, but f2() calls A's.
When you declare a function virtual, you are saying that when we call it we should use the vtable to look up the right version of the function to call, and so you will always get the most derived version of the function, even if you reference it as an ancestor type. Without virtual, it will simply use the definition in the type you are referencing it as.
The distinction is when you have a reference or pointer to the base class. A call to a virtual function will call the most-derived version while a call to a normal function will call the base-class version.
If you're using a variable directly or a reference or pointer to the most-derived class, there is no practical difference.
TL;DR
The only way to take advantage of the polymorphism in C++ is via virtual functions and pointers (and references). The virtual keyword will tell the compiler to allocate a virtual function table where to look when deciding what version of the virtual function to call when dealing with pointer to the base class with a dynamic type that is of a child class.
How does polymorphism work in C++
Let's take a simple example:
class A { public: virtual void eat() { std::cout << "Class A" << std::endl; }
class B : public A {};
class C : public B { virtual void eat() { std::cout << "Class C" << std::endl; }
Note: the virtual keyword could be omitted after the first function/method definition.
The following:
A a; B b; C c;
A* ptrA = &a; A* ptrB = &b; A* ptrC = &c;
ptrA->eat();
ptrB->eat();
ptrC->eat();
will print:
Class A
Class A
Class C
If we wouldn't have declared the function eat virtual, the output would have simply been:
Class A
Class A
Class A
But why
A* ptrA = &a; A* ptrB = &b; A* ptrC = &c;
Instead of
A* ptrA = &a; B* ptrB = &b; C* ptrC = &c;
With the second version, the eat() method can simply be redefined for each derived class, without the need for virtual, right?
I have two classes:
class A
{
public:
int i;
};
class B : public A
{
public:
int i;
};
Suppose that I created an object for class B
B b;
Is it possible to access A::i using b?
Is it possible to access A::i using b?
Yes!
How about b.A::i? ;)
Yes:
int main()
{
B b;
b.i = 3;
b.A::i = 5;
A *pA = &b;
B *pB = &b;
std::cout << pA->i << std::endl;
std::cout << pB->i << std::endl;
}
Yes you can. To find out read this
An override method provides a new implementation of a member inherited from a base class. The method overridden by an override declaration is known as the overridden base method. The overridden base method must have the same signature as the override method.
From within the derived class that has an override method, you still can access the overridden base method that has the same name by using the base keyword. For example, if you have a virtual method MyMethod(), and an override method on a derived class, you can access the virtual method from the derived class by using the call:
base.MyMethod()
Two ways:
struct A{
A():i(1){}
int i;
};
struct B : A{
B():i(0), A(){}
int i;
};
int main(){
B b;
cout << b.A::i;
cout << (static_cast<A&>(b)).i;
}
It is possible, as others replied.
But in the example you posted, the base and derived members are the same, the data type was not overriden.
This would be relevant in the case of derived classes that define a new data type for the base members as shown in this post: C++ Inheritance. Changing Object data Types