I have an error while calling a virtual function that is defined in Derived class but not present in Base class? Why this error when I have pointer pointing to derived class?
#include<iostream.h>
class A{
public:
virtual void fun()
{cout<<"A::fun()";
}
};
class B : public A
{
public:
virtual void fun()
{cout<<"B::fun()";
}
virtual void func()
{cout<<"B::func";
}
};
int main()
{
A *obj1=new B;
obj1->fun();
obj1->func();
}
This is the most un-friendly question I've seen yet on SO.
Of course you're getting the error (I'm guessing when you call obj1->func()) because your variable is a pointer to an object of type A, not B. So even though you've created a B, you're variable is acting like an A because the compiler has no idea it's actually a B saved in it.
You need to change your variable to point to a B: B* obj1 = new B;
Or you need to cast your pointer to B before you call func: ((B*)obj1)->func();
This is an error because although you at runtime have a pointer to a derived class, the compiler at compile time (when it emits the error message) doesn't know this - it just knows you have a pointer to the base class, and the base class doesn't have this function. So you have to declare the function as virtual in the base so that the compiler knows what you are talking about.
And BTW, its <iostream>, not <iostream.h>.
Related
Virtual function d() in the base class A is overidden by a private method in derived class B. When d() is invoked on an instance of B from outside, via a pointer of type A *, it is B::d() that runs, even though it is private to B.
Why does this happen? Shouldn't it be impossible for code outside B to invoke B's private methods?
Demo
#include<iostream>
using namespace std;
class A {
public:
virtual void d(){
cout<<" gfgd ";
}
};
class B :
public A
{
private:
void d(){
cout<<"hytyhtht";
}
};
int main() {
A *a1;
B b;
a1=&b;
a1->d();
return 0;
}
Output:
hytyhtht
The public/protected/private access-rules are enforced at compile-time, not at run-time, which means that they have to rely on logic that the compiler can enforce at compile-time.
In particular, the compiler knows that you are calling the d() method using a A* pointer, and that class A has declared virtual void d() to be a public method, so that means it's okay to call the method.
In general the compiler can't know at compile-time that your pointer is really pointing to a B object, so even if it wanted to it wouldn't be able to flag the call as a compile-time error. (Well, maybe in your particular example it could, but in many cases the compiler doesn't know what the type of the pointer-to object will be, it only knows the type of the pointer)
For example:
// in someotherfile.cpp
void MyFunction(A * a)
{
a->d(); // should this compile, or not?
}
Suppose we have the following code:
class Base
{
public:
virtual void foo() const
{ cout << "In Base::foo\n"; }
}
class Derived : public Base
{public:
virtual void foo()
{ cout << "In Derived::foo\n"; }
}
void main()
{
Base* b = new Derived();
b->foo();
delete b;
}
It will give us the following output: In Base::foo.
Now suppose I want to get - without changing the main function - the follwing output instead the one given above:
In Derived::foo
As far as I understand, I should override the function foo() of in the base, to get the output of the method
foo() in the inheriting class which is class 'Derived'.
But the problem is that in that case I can't using the command override, becuase the method in the base is defined as constant , which in the other class it is not.
So, how should I if then overriding that method ?
In order to override the function void foo() const of the base class, you must declare the function void foo() const in the derived class. You've declared the function void foo() instead (note the lack of const), which doesn't override the function in the base, because it has a different declaration.
So, how should I if then overriding that method ?
Add the missing const qualifier.
P.S. Few other bugs in your program:
main must return int.
Class definitions must end in a semicolon.
Deleting a derived object through a pointer to base has undefined behaviour unless the destructor of the base is virtual.
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
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Public virtual function derived private in C++
class B
{
private:
int b;
public:
B(int i);
virtual void show()
{
cout<<"B::show()called. "<<b<<endl;
}
};
B::B(int i=0)
{
b=i;
}
class D:public B
{
private:
int d;
void show()
{
cout<<"D::show() called. "<<d<<endl;
}
public:
D(int i, int j);
};
D::D(int i=0, int j=0):B(i)
{
d=j;
}
void fun(B&obj)
{
obj.show();
}
/*if I redefine fun() as follow, the result would be the same
void fun(B*obj)
{
obj->show();
}
*/
int main()
{
D *pd=new D(5,8);
fun(*pd); //K
delete pd;
}
The output of the program is "D::show() called.", which means the virtual function declared in the private part of class D is invoked. Don't you think it weird? How could a private member of a class be accessed from outside?
The crucial part is that your function void fun(B&obj) takes an argument of static type B& (so a conversion happens at the call site; the same happens with B*).
Since B::show is public, your code has no problem calling it. When the compiler looks at how to dispatch the call it sees that show is virtual so it calls D::show. The fact that you could not have called D::show if obj was of type D is irrelevant.
Unlike Java, in C++ the access specifier doesn't affect the virtual functions.
'Access specifier' is a compile time check which is made on the class method with respect to static type of the handle. e.g. in your code obj is of type B and B::show() is public; hence the code is legal.
obj may refer dynamically to some other type than B.
Remember that virtual function dispatch is a runtime phenomena. (In Java it would have given a runtime error.)
B::show() is public and once it's invoked, the virtual functionality will kick in and call the appropriate object's function.
If you try calling D::show() directly then you will get the expected compiler error.
It's not weird. In B, the method is public. You can call show() on a B object.
It's just that the method gets dispatched to an extending class.
I have a class (B) that inherits another class (A). I want to call a function from class A that has been overridden. I also want to be able to call the overridden function independent of what class inherited the base (say class C : public A , where I want to call C's version of the function.)
Here's an example
class A {
public:
void callF();
virtual void f() {};
};
class B : public A {
public:
void f();
};
void A::callF()
{
//FYI, I want to be able to call this without knowing what the super class is.
f();
}
void B::f()
{
std::cout << "I want this function to be called, but instead the default f() is called.";
}
Edit:
In my real code, I have an std::vector<A> aVector;. Then I would call aVector.push_back(B());. If I called aVector[0].callF();, The default a::f() would be called.
As answered below, I have a problem with slicing.
Your construction:
vector_of_A.push_back( B() );
doesn't store a B in the vector. It constructs a B, then constructs an A from that, then stores that A in the vector. As a consequence, you experience slicing.
See this for more info:
https://stackoverflow.com/a/4403759/8747
Your code is correct.
You may be getting the behavior you observed because your were calling f() or callF() from the constructor of A. That's the only case I can think of where A::f() would get invoked instead of B::f().
Your code works for me with this little test program:
int main()
{
// Instantiate B, and reference it via a base class pointer.
A* b = new B;
b->callF();
delete b;
}
Output:
I want this function to be called, but instead the default f() is called.
When calling a virtual member function within a base class member function, it's the derived member function that will be invoked.