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?
}
Related
#include <iostream>
struct A {
virtual void a() {
puts("A");
}
};
struct B {
virtual void b() {
puts("B");
}
};
struct C {
virtual void c() {
puts("C");
}
};
struct D : public A, public B, public C {
virtual void c() {
C::c();
puts("cd");
}
};
int main() {
A* obj = new D;
obj->a();
B* b = (B*)obj;
b->b();
C* c = (C*)obj;
c->c();
return 0;
}
I have this code where I have non virtual multiple inheritance. However, it seems to call the wrong virtual function when I call the functions in the main function.
Instead of outputting:
A
B
C
cd
It outputs:
A
A
A
What puzzles me is that when I change the code to doing this:
B* b = (B*)(D*)obj;
b->b();
C* c = (C*)(D*)obj;
c->c();
It outputs what I would expect (see above). Afaik doing a double pointer cast like this wouldn't effect anything and would be optimized out by the compiler. But it seems to be changing what virtual function is being called.
Can someone explain why this would change what virtual function is being called?
Notes:
I printed the pointers at each step, they are the same.
I want to avoid using dynamic_cast (although it does work) as it's too slow for what I need it to do.
Can someone explain why this would change what virtual function is being called?
Generally, a C-style cast between pointer types won't change the value of the pointer and so will have no effect. There is, however, one exception.
A cast between a class and a parent or child class can change the value of the pointer. For example:
class A
{ int a; };
class B
{ int b; };
class C : public A, public B
...
Now, a pointer to an instance of class A will probably have the same value as a pointer to its a member and a pointer to an instance of class B will probably have the same value as a pointer to its b member. A pointer to an instance of class C can't have the same value as a pointer to both its A::a and its B::b members since they're distinct objects.
A function expecting a B* can be passed a C* since a C is a B. Similarly, a function expecting an A* can be passed a C* for the same reason. But at least one of these will require a value change to the pointer.
So casts between these types will change the values, the others are all no-ops.
Of course, all of this is UB. You are casting between unrelated types and then dereferencing them.
I want to avoid using dynamic_cast (although it does work) as it's too slow for what I need it to do.
That seems very hard to believe.
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.
I'm slightly confused about runtime polymorphism. Correct me if I am wrong, but to my knowledge, runtime polymorphism means that function definitions will get resolved at runtime.
Take this example:
class a
{
a();
~a();
void baseclass();
}
class b: class a
{
b();
~b();
void derivedclass1();
}
class c: class a
{
c();
~c();
void derivedclass2();
}
Calling methodology:
b derived1;
a *baseptr = &derived1; //here base pointer knows that i'm pointing to derived class b.
baseptr->derivedclass1();
In the above calling methodology, the base class knows that it's pointing to derived class b.
So where does the ambiguity exist?
In what cases will the function definitions get resolved at runtime?
This code, at run time, calls the correct version of f() depending on the type of object (A or B) that was actually created - no "ambiguity". The type cannot be known at compile-time, because it is selected randomly at run-time.
struct A {
virtual ~A() {}
virtual void f() {}
};
struct B : public A {
virtual void f() {}
};
int main() {
A * a = 0;
if ( rand() % 2 ) {
a = new A;
}
else {
a = new B;
}
a->f(); // calls correct f()
delete a;
}
There is no ambiguity exists in the example provided.
If the base class has the same function name as the derived class, and if you call in the way you specified, it will call the base class's function instead of the derived class one.
In such cases, you can use the virtual keyword, to ensure that the function gets called from the object that it is currently being pointed. It is resolved during the run time.
Here you can find more explanation..
Turn this
void baseclass();
to
virtual void baseclass();
Override this in your Derived classes b and c. Then
b *derived1 = new derived1 ();
a *baseptr = derived1; //base pointer pointing to derived class b.
baseptr->baseclass();
will invoke derived1 definition, expressing run time polymorphism. And do remember about making your destructor virtual in Base. Some basic reading material for polymorphism
Runtime means that exact method will be known only at run time. Consider this example:
class BaseClass
{
public:
virtual void method() {...};
};
class DerivedClassA : public BaseClass
{
virtual void method() {...};
};
class DerivedClassB : public BaseClass
{
virtual void method() {...};
};
void func(BaseClass* a)
{
a->method();
}
When you implement your ::func() you don't know exactly type of instance pointed by BaseClass* a. It might be DerivedClassA or DerivedClassB instance etc.
You should realize, that runtime polymorphism requires special support from language (and maybe some overhead for calling "virtual" functions). In C++ you "request" for dynamic polymorphism by declaring methods of base class "virtual" and using public inheritance.
You need to have some useful business method declared in the base and in each derived class. Then you have code such as
a->someMethod();
Now the a pointer might point to an instance of any of the derived classes, and so the type of what a is pointing to must determine which someMethod() is called.
Lets have an experiment
#include <iostream>
using namespace std;
class aBaseClass
{
public:
void testFunction(){cout<<"hello base";}///Not declared as virtual!!!!
};
class aDerivedClass:public aBaseClass
{
public:
void testFunction(){cout<<"hello derived one";}
};
class anotherDerivedClass:public aDerivedClass
{
public:
void testFunction(){cout<<"hello derived two";}
};
int main()
{
aBaseClass *aBaseClassPointer;
aBaseClassPointer=new aDerivedClass;
aBaseClassPointer->testFunction();
}
The above code does not support run time polymorphism. Lets run and analyze it.
The output is
hello base
Just change the line void testFunction(){cout<<"hello base";} to virtual void testFunction(){cout<<"hello base";} in aBaseClass. Run and analyze it. We see that runtime polymorphism is achieved. The calling of appropriate function is determined at run time.
Again change the line aBaseClassPointer=new aDerivedClass to aBaseClassPointer=new anotherDerivedClass in main function and see the output. Thus the appropriate function calling is determined at run time (when the program is running).
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>.