Maybe a silly question.
Suppose I have the following:
class A{
int x;
int y;
virtual int get_thing(){return x;}
};
class B : public A {
int get_think(){return y;}
};
In the example above, B::get_thing returns x because the overriding code has a typo.
How can I ensure, at compile time that the get_thing function has been overridden in class B so that it returns y?
Assuming A::get_thing is virtual, and assuming class B is derived from class A, and you have C++11 support, you can use the override special identifier:
class B : public A{
int get_think() override {return y;}
};
This would produce a compiler error. Note that this is based on the signature of the method, i.e. its name, cv qualifiers, and types of the parameters. The return type or the body of the function do not come into it.
First you have an error in your example, I think B supposed to be a child of A, isn't it?!
But answer is: you can compare address of functions( of course if you want it and can't check it in programming time ):
if( reinterpret_cast<void*>(&B::get_think) != reinterpret_cast<void*>(&A::get_think) ) {
std::cout << "B override A";
} else {
std::cout << "B override A";
}
Related
Here is the code
,it is my homework using overriden methods teacher told us to analyze the code. I know the code is outputting 2, I have no clue how this code work.
public:
int a;
virtual void who(void) { a = 1; }
};
class B:public A{
public:
int a;
void who(void) { a = 2; }
};
class C :public B {
};
int main(void) {
A x; B y; C z; A *p;
p = &z;
p->who();
cout << z.a << endl;
system("pause");
return 0;
}
B overrides the who() function of its parent, A. This is called polymorphism. C inherits from B, but doesn't override anything; thus, it uses all of the implementation of B.
p is a pointer to an object of class A. One of the key features of class inheritance is that a pointer to a derived class is type-compatible with a pointer to its base class [1].
This means that when you call a member function of a pointer (p->who()), and the class of the object the pointer is pointing to overrides a member of its parent, is going to use the overridden member.
Sources:
[1] http://www.cplusplus.com/doc/tutorial/polymorphism/
as long as you create a function with same input and output with name; in short: same function declaration.. the new one will be used as you refer to one which has super class that has same function. in your case; super class for C is B and it doesn't see A, but B sees A and use all functions it has except what's B declare a new implementation for.
I have a somewhat basic question on inheritance that i can seem to figure out, I've done a search and not found what I was looking for so I thought I'd ask here (not sure if title of what I'm looking for is correct).
To keep things simple I've made a bit of example code to illustrate what I'm not getting.
Basically if I have a parent class A and two child classes B & C,
where A contains common stuff (say an id with get/set),
while B & C have functions that are class specific.
If you declare a class B like: A *bObject = new B();
how do you then access the class specific functionbObj->specific()`?
I've tried virtual but that requires both B & C to have the same function name / prototype declared.
I've also tried declaring the abstract in A, but that requires it to be prototype to be in A.
Where am i going wrong here? any help on this, probably basic issue would be helpful.
#include <iostream>
using namespace std;
// A class dec
class A
{
public:
A(void);
~A(void);
char id;
void setId(char id);
char getId();
};
// B class dec - child of A
class B :
public A
{
public:
B(void);
~B(void);
void sayHello();
};
//C class dec - child of A
class C :
public A
{
public:
C(void);
~C(void);
void sayGoodby();
};
//a stuff
A::A(void)
{
}
A::~A(void)
{
}
void A::setId(char id)
{
this->id = id;
}
char A::getId()
{
return this->id;
}
//b stuff
B::B(void)
{
this->setId('b');
}
B::~B(void)
{
}
// c stuff
C::C(void)
{
this->setId('c');
}
C::~C(void)
{
}
void C::sayGoodby()
{
std::cout << "Im Only In C" << std::endl;
}
// main
void main ()
{
A *bobj = new B();
A* cobj = new C();
std::cout << "im class: " << bobj->getId() << endl;
bobj->sayHello(); // A has no member sayHello
std::cout << "im class: " << cobj->getId() << endl;
cobj->sayGoodby(); // A has no member sayGoodby
system("PAUSE");
}
Thank you for your time!
To access methods unique to a derived class, you need to cast the base class pointer to the correct derived class type first (a downcast):
A *bobj = new B();
bobj->sayHello(); // compile error
dynamic_cast<B*>(bobj)->sayHello(); // works
dynamic_cast<C*>(bobj)->sayGoodbye(); // run-time error - probably crashes with a segfault/access violation.
dynamic_cast ensures run-time type safety but adds a small overhead to the cast; for pointer casts, it returns a null pointer if the pointed-to object is not actually a B, and you should check the return value before using it. Alternatively, if you are really sure that the pointer you are casting is pointing to the correct object, you can use static_cast which saves you the cost of the run-time checking, but if the pointer is not pointing to the right object, you get undefined behavior.
A *bobj = new B();
A* cobj = new C();
Here instance of B and C is pointed by pointer of A. Since A have no virtual function for B and C's member function sayHello() and sayGoodbye(), they could not called by bobj->sayHello() and cobj->sayGoodbye(). It is not what polymorphism should be do.
Class A should be:
class A
{
public:
A(void);
~A(void);
char id;
void setId(char id);
char getId();
virtual void sayHello(){/* to do */ };
virtual void sayGoodbye(){ /* to do */ };
};
Then the bobj->sayHello(); and cobj->sayGoodbye(); could be called without complaning.
A *bobj = new B();
The static type of bobj is A *. So, at compile time, the compiler looks for the member functions in the class A definition, what ever you tried to access through bobj. Now,
bobj->sayHello();
the compiler will look for the sayHello in class A since the type of bobj is A *. Compiler doesn't care to look into the class B definition to resolve the call. Since the compiler didn't find it sayHello member in A, it is complaining.
However, the dynamic type of bobj is B * and that is a where call is dispatched depending on the dynamic type.
To resolve the issue, you need to virtual functions of the same in class A.
if you really want to call a function like this, you can do like this:
A* bobj = new B();
((B*)bobj)->sayHello();//this can be dangerous if bobj is not an instance of class B
however, the problem here is you do the design wrongly.
basically, if you create an class A, and subclass it to B and C.
And then assign A* bobj = new B(); you are splitting the interfaces and implementations. That means you will use bobj as if it is an instance of class A. and you will not call the functions in B or C. B & C are implementations of interface class A.
it's just like you hire someone to build your house. You give them your blueprint(interfaces) and hire them to build. you can alter the blueprint as you like, they will do whatever in blueprint. but you can't order them directly(just like you can't call the sayHello() directly from bobj).
You can use a down cast via dynamic_cast<>. You can implement a template method in your base class A to facilitate the down cast:
class A
{
public:
A(void);
virtual ~A(void);
char id;
void setId(char id);
char getId();
template <typename CHILD, typename R, typename... ARGS>
R invoke (R (CHILD::*m)(ARGS...), ARGS... args) {
CHILD *child = dynamic_cast<CHILD *>(this);
if (child) return (child->*m)(args...);
std::cout << "down cast error: " << typeid(CHILD).name() << std::endl;
}
};
If that particular instance of A was not the base of CHILD, then dynamic_cast<CHILD *>(this) result in NULL. Note that the virtual destructor in A is required for the dynamic_cast<> to work.
So, you can use it like this:
std::unique_ptr<A> bobj(new B());
std::unique_ptr<A> cobj(new C());
bobj->invoke(&B::sayHello);
bobj->invoke(&C::sayGoodbye);
cobj->invoke(&B::sayHello);
cobj->invoke(&C::sayGoodbye);
Only the first and last invocations are valid. The middle two will cause the "down cast error" message to be printed.
#include<iostream>
class A {
private :
int _a;
public :
A(int i=0) : _a(i){}
virtual void setA(int i) { _a = i;}
virtual int getA(){ return _a;}
};
class B : public A
{
private :
int _b;
public :
B(int i) : _b(i){}
virtual void setB(int i) { _b = i;}
virtual int getB(){ return _b;}
};
int main(){
A* a1 = new B(10);
std::cout << a1->getA() << "\t " << a1->getB() << std::endl;
return 0;
}
While compiling I get the following error:
test.cpp(28): error C2039: 'getB' : is not a member of 'A'
Shouldn't a1 get getB since it's actually a pointer to B?
The compiler tells you the exact reason:
'getB' : is not a member of 'A'
The compiler does a compile time checking based on the type of the pointer, since it cannot find the method in A it reports so. Note that at compile time the compiler may or may not know what object the pointer a1 points to, it might be A or B or any class publically derived from A. The compiler only checks type of the pointer and checks if the member being accessed belongs to that class.
For you, a1 points to a object of B and hence can be treated like B but for the compiler a1 is a pointer of the type A and at compile time it only treats it as A.
Whilst the answer to "why this doesn't work" is well covered above, I think I should but in on the "how do you solve this".
The simple answer is to implment a getB() for A. This is generally the right thing to do - and if it's somehow "forbidden" to call getB on objects that don't have this property, then do something about it - print an error, exit the program, or whatever is "right" when someone does something wrong in the code (preferrably print a message somewhere, then stop, so that it's clear what has gone wrong and it can be debugged).
The alternative, using for example dynamic cast, will also work. But you still have to either know whether the object is a B class or not - or check if the pointer returned NULL.
The whole point with virtual functions is that you override the ones in the baseclass with new variants in the derived class. It is not there to support adding NEW functions in the derived classes. The way to support "new functions" is to for example add a parameter:
class A
{
public:
...
virtual int get(char v)
{
if (v == 'A') return _a;
else
{
std::cerr << "Error: Requesting invalid variable: '" << v << "'" << std::endl;
return -1;
}
}
...
}
class B: public A
{
...
virtual get(char v)
{
if (v == 'B')
return b;
return A::get(v);
}
...
}
Now this works with a slight modification:
std::cout << a1->get('A') << "\t " << a1->get('B') << std::endl;
You must have a member function in the class A:
virtual int getB()
{
// do something or not
}
And after that when you call a1->getB() it will call the member function of class B.
An alternative would be to use dynamic_cast on a1:
A* a1 = new B(10);
B* b1=dynamic_cast<B*>(a1);
std::cout << b1->getA() << "\t " << b1->getB() << std::endl;
The compiler doesn't know about a's dynamic type information. You can cast it to its dynamic type using dynamic_cast:
dynamic_cast<B*>(a1)->getB();
Live Demo
Though a1 is a pointer to a class B object,compiler does not know a1 points to a B object until run time.So in compile time,you will encounter an error because there is no getB method in class A.
I wanted to have confirmation about the following things:
Virtual Mechanism:
I f I have a base class A and it has a Virtual method, then in the derived class generally, we do not include the virtual statement in the function declaration. But what does a virtual mean when included at the dervied class definition.
class A
{
public:
virtual void something();
}
class B:public A
{
public:
virtual void something();
}
Does, that mean that we want to override the method somethign in the classes that derive from the class B?
Also, another question is,
I have a class A, which is derived by three different classes.Now, there is a virtual method anything(), in the base class A.
Now, if I were to add a new default argument to that method in the base class, A::anything(), I need to add it in all the 3 classes too right.
My pick for the answers:
If a method which is virtual in the base class is redefined in the derived class as virtual then we might mean that it shall be overridden in the corresponding derived classes which uses this class as base class.
Yes.If not overriding does not have any meaning.
Pls let me know if what I feel(above 2) are correct.
Thanks,
Pavan Moanr.
The virtual keyword can be omitted on the override in the derived classes. If the overridden function in the base class is virtual, the override is assumed to be virtual as well.
This is well covered in this question: In C++, is a function automatically virtual if it overrides a virtual function?
Your second question is about default values and virtual functions. Basically, each override can have a different default value. However, usually this will not do what you expect it to do, so my advice is: do not mix default values and virtual functions.
Whether the base class function is defaulted or not, is totally independent from whether the derived class function is defaulted.
The basic idea is that the static type will be used to find the default value, if any is defined. For virtual functions, the dynamic type will be used to find the called function.
So when dynamic and static type don't match, unexpected results will follow.
e.g.
#include <iostream>
class A
{
public:
virtual void foo(int n = 1) { std::cout << "A::foo(" << n << ")" << std::endl; }
};
class B : public A
{
public:
virtual void foo(int n = 2) { std::cout << "B::foo(" << n << ")" << std::endl; }
};
int main()
{
A a;
B b;
a.foo(); // prints "A::foo(1)";
b.foo(); // prints "B::foo(2)";
A& ref = b;
ref.foo(); // prints "B::foo(1)";
}
If all your overrides share the same default, another solution is to define an additional function in the base class that does nothing but call the virtual function with the default argument. That is:
class A
{
public:
void defaultFoo() { foo(1); }
virtual void foo(int n) { .... }
};
If your overrides have different defaults, you have two options:
make the defaultFoo() virtual as well, which might result in unexpected results if a derived class overload one but not the other.
do not use defaults, but explicitly state the used value in each call.
I prefer the latter.
It doesn't matter whether you write virtual in derived class or not, it will always be virtual because of the base class, however it is still better to include virtual to explicitly state that it is virtual and then if you accidentally remove that keyword from base class it will give you compiler error (you cannot redefine non-virtual function with a virtual one). EDIT >> sorry, I was wrong. You can redefine non-virtual function with a virtual one however once it's virtual all derived classes' functions with same signature will be virtual too even if you don't write virtual keyword. <<
If you don't redefine virtual function then the definition from base class will be used (as if it were copied verbatim).
If you wish to specify that a virtual function should be redefined in dervied class you should not provide any implementation i.e. virtual void something() = 0;
In this case your class will be an abstract base class (ABC) and no objects can be instantiated from it. If derived class doesn't provide it's own implementetian it will also be an ABC.
I'm not sure what do you mean about default arguments but function signatures should match so all parameters and return values should be the same (it's best to not mix overloading/default arguments with inheritance because you can get very surprising results for example:
class A
{
public:
void f(int x);
};
class B:public A
{
public:
void f(float x);
};
int main() {
B b;
b.f(42); //this will call B::f(float) even though 42 is int
}
Here is a little experiment to test out what you want to know:
class A {
public:
virtual void func( const char* arg = "A's default arg" ) {
cout << "A::func( " << arg << " )" << endl;
}
};
class B : public A {
public:
void func( const char* arg = "B's default arg" ) {
cout << "B::func( " << arg << " )" << endl;
}
};
class C : public B {
public:
void func( const char* arg ) {
cout << "C::func( " << arg << " )" << endl;
}
};
int main(int argc, char* argv[])
{
B* b = new B();
A* b2 = b;
A* c = new C();
b->func();
b2->func();
c->func();
return 0;
}
result:
B::func( B's default arg )
B::func( A's default arg )
C::func( A's default arg )
conclusion:
1- virtual keyword before A's func declaration makes that function virtual in B and C too.
2- The default argument used is the one declared in the class of pointer/reference you are using to access the object.
As someone pointed out, a function in a derived class with the same name and type signature as a virtual function in the base class is automatically always a virtual function.
But your second question about default arguments is interesting. Here is a tool for thinking through the problem...
class A {
public:
virtual void do_stuff_with_defaults(int a = 5, char foo = 'c');
};
is nearly equivalent to this:
class A {
public:
virtual void do_stuff_with_defaults(int a, char foo);
void do_stuff_with_defaults() { // Note lack of virtual keyword
do_stuff_with_defaults(5, 'c'); // Calls virtual function
}
void do_stuff_with_defaults(int a) { // Note lack of virtual keyword
do_stuff_with_defaults(a, 'c'); // Calls virtual functions
}
};
Therefore you are basically having virtual and non-virtual functions with the same name but different type signatures declared in the class if you give your virtual function default arguments.
On way it isn't equivalent has to do with being able to import names from the base class with the using directive. If you declare the default arguments as separate functions, it's possible to import those functions using the using directive. If you simply declare default arguments, it isn't.
below is the small program.
i want to check the value of the private variable x of class A using the object of class B.
is it possible ever?
#include<stdio.h>
#include<conio.h>
#include<iostream>
class A {
int x;
public:
A() {
x=10;
}
};
class B : public A {
public:
int x;
};
int main()
{
B obj;
obj.x=20;
std::cout<< obj.x;
getch();
}
This will output 20, but how can i check the value of x as 10 which is in class A?
i wanted to know whether we can check the value without making x as protected!
You'll have to make the variable protected, or, you can create a protected member method in class A which returns the variable x.
By using the 2nd approach (protected member method or property (is that possible in C++?), class B can read the variable, but cannot change it.
Derived classes cannot see ancestor privates. You can use "protected" for descendents to see the data, but not unrelated classes.
In addition to the private / protected issue, your B::x member over-shades the x of A. So even if both were public, you'd have to write b.A::x. Looks weird, but works (see code below) ....
This is syntax-wise. You should tot do this, of course, as everybody here say. use protected members with meaningful names, and accessor functions
class A {
public:
int x;
};
class B: public A {
public:
int x;
void f() { std::cout << "B::x=" << x << ", A::x=" << A::x << '\n'; }
};
int main()
{
B b;
b.A::x = 10;
b.x = 20;
b.f();
}
output:
B::x=20, A::x=10
You can not examine the value of private members of base class. So: add an accessor in A or make A::x protected.
Make x in A protected and write a method in B that looks something like this:
int getAX(){
return A::x
}
You shouldn't.
Since your A class tells the member is private, nobody but A can access it.
If B is-an-A, the same rule is valid: A::x is still inaccessible.
Your wanting to access it means you either need a different kind of A (i.e. make A::x public), or you want the wrong thing.
Well, if you really want to know if it's possible: it is. public, protected and private are only compile time checks. One possible option to circumvent them during runtime is the following:
#include <iostream>
class A{
int x;
A() : x(10){}
};
struct pubA{
int x;
};
int main(){
A a;
// evil casting
pubA* pa = reinterpret_cast<A*>(&a);
std::cout << pa->x << std::endl; // should print 10
}
That said, don't do it. There is a reason for these keywords. (The above code is untested, 'caus I'm writing from my iPod. If reinterpret_cast doesn't work, use old C-style cast: pa = (pubA*)&a.)