How does the this pointer behaves when used inside a base class method:
class Base{
public:
int a;
Base() : a(5) {}
void func(){
std::cout << " value is : " << this->a << std::endl;
}
};
class Derived : public Base{
private:
int a;
public:
Derived() : a(1){}
void func1(){
std::cout << " value is : " << this->a << std::endl;
}
};
int main(){
Derived d;
d.func();
d.func1();
}
the output of the code is :
value is : 5
value is : 1
As i am using the same object to call both the functions. So will the value of this pointer differ in methods for base and derived class ?
this->a is equivalent to a in that context, so it has nothing to do with the base pointer.
The member a is resolved statically, and the derived class hides the base class member, since they're both named a.
To check the this pointer itself, you can print it directly:
std::cout << this;
It will be the same for both objects.
The main thing to take from this is that Base::a and Derived::a are different. Try the following in Derived:
void func1(){
std::cout << "derived value is : " << a << std::endl;
std::cout << " base value is : " << Base::a << std::endl;
}
You would have to do this->Base::a to access Base's a. Else you always access Derived::a.
this pointer will always point to current object in which it exists.
When func is called, Base class is used and base class field is printed. but,
When func1 is called, Derived class is used and it's field is printed.
Try commenting this line Derived() : a(1){} and you'll get more clarity.
Related
I have following code snippet:
class base
{
public:
virtual void print(char a){ std::cout << " Base\n"; }
};
class derived : public base
{
public:
void print(float a) { std::cout << " Derived\n"; }
};
int main() {
base* d = new derived;
d->print(1.5);
}
Output is Base.
Why is the output coming from the base function and not from the derived one?
You have not overridden the function in the base class, you have overloaded it: The version in the derived class takes a float as an argument, and is quite a different beast from the base class method which takes a char. Moreover, the float version in the derived class shadows the base class version: The base class version becomes inaccessible for calls on the derived type.
As such, the following code
Derived d;
d.print('a');
d.print(1.5);
will print
Derived
Derived
because the call is resolved by the compiler to the only version of print() that's available in Derived.
Likewise, when you call d->print(1.5) through a pointer to Base, the derived class' version is inaccessible to the call: The compiler looks at the base class, sees that there is no print() method defined with a float argument, and converts the argument to char instead. It then calls the only implementation of print(char), which happens to be supplied by the base class.
If you simply change the signature of the print() method in the derived class to match that of the base class, the odd behavior will go away.
When you declare Base* d = new Derived;, the type of the class is Base, as printed by typeid(d).name(), so this instance doesn't have access to child class methods. If you change the type to Derived, you'll call the child method:
#include <iostream>
#include <typeinfo>
class Base
{
public:
virtual void print(char a) {
std::cout << " Base " << std::endl;
}
};
class Derived : public Base
{
public:
void print(float a) {
std::cout << " Derived " << std::endl;
}
};
int main()
{
Derived* d = new Derived;
std::cout << "class type is: " << typeid(d).name() << std::endl;
d->print(1.5);
return 0;
}
Output:
class type is: P7Derived
Derived
Furthermore, declaring the parent class print method virtual doesn't allow an instance of Base to call the child version of print because the child hasn't overridden it (different headers). Creating an instance of Base with Base *d = new Derived; and changing the Derived print method header to void print(char a) in the Derived class would allow you to call the child print method and output Derived, even from an instance of Base, using the virtual keyword.
#include <iostream>
#include <typeinfo>
class Base
{
public:
virtual void print(char a) {
std::cout << " Base " << std::endl;
}
};
class Derived : public Base
{
public:
void print(char a) {
std::cout << " Derived " << std::endl;
}
};
int main()
{
Base* d = new Derived;
std::cout << "class type is: " << typeid(d).name() << std::endl;
d->print(1.5);
return 0;
}
Output:
class type is: P4Base
Derived
I didn't know what to give as a title, I expect more experienced stackoverflow.com users to improve it.
Let's say we have the class A
class A {
void hello(){ cout << "i'm an A" << endl; }
}
and its sub-class B
class B: public A {
void hello(){ cout << "i'm a B" << endl; }
}
Then we did somewhere in our program
A* array[2];
array[0] = new A;
array[1] = new B;
array[0]->hello(); // output: "i'm an A"
array[1]->hello(); // output: "i'm a B"
why doesn't the array[1].hello(); output I'm a B since we instanciated a B object for that base-class pointer ? and how to make it happen ?
Couple of changes here:
make function hello in class A, a virtual and public: because by default it is private
class A {
public:
virtual void hello(){ cout << "i'm an A" << endl; }
};
Similarly make hello in class B virtual
class B: public A {
virtual void hello(){ cout << "i'm a B" << endl; }
};
You have to make hello a virtual function:
class A {
virtual void hello() { cout << "i'm an A" << endl; }
};
class B : public A {
virtual void hello() override { cout << "i'm a B" << endl; } // 1)
};
This tells the compiler that the actual function should not be determined by the static type (the type of the pointer or reference) but by the dynamic (run-time) type of the object.
1) The overridekeyword tells the compiler to check, if the function actually overrides a hello function in the base class (helps e.g. to catch spelling mistakes or differences in the parameter types).
Since you have inherited class A in class B, derived class B will call the function from the Base class. You need to override the function in class B, as you want to change the Base class functionality.
You can do this with the override and virtual keywords.
http://en.cppreference.com/w/cpp/language/override
I have a code snippet below:
#include <iostream>
using namespace std;
class Base {
public:
Base() : b(0) {}
int get();
virtual void sayhello() { cout << "Hello from Base with b: " << b << endl; }
private:
int b;
};
int Base::get() {sayhello(); return b;}
class Derived : public Base {
public:
Derived(double b_):b(b_){}
void sayhello() { cout << "Hello from Derived with b: " << b << endl; }
private:
double b;
};
int main() {
Derived d(10.0);
Base b = d;
cout << "Derived b: " << d.get() << endl;
cout << "Base b: " << b.get() << endl;
}
Run the compiled executable and I find the result is out of my expectation on my llvm-g++ 4.2 machine. The output on my box is as
Hello from Derived with b: 10
Derived b: 0
Hello from Base with b: 0
Base b: 0
What I want to do in the code is to override a member field (b) in Derived class.
Since I think both Base and Derived need to access this field, I define a get member function in Base, thus Derived can inherit it.
Then I try to get the member field from different objects.
The result shows that I still get original b in Base by d.get() instead of that in Derived, which is what I expected the code to do.
Anything wrong with the code (or my understanding)? Is this behavior specified in the specification? What is the right way to override a member field and properly define its getter and setter?
The new b added in the derived class doesn't override base's b. It just hides it.
So, in the derived class you have two b and the virtual method prints corresponding b.
You can't simply override a member field, and as Base::get is compiled, the b variable is resolved to Base::b so this method will always use this value and not a value from another field with the same name in a derived class.
The usual way to override an attribute is to override the way you access it, i.e. override the accessors (getter and setter).
You can achieve something like that by decorating the getter, but the getter return type will always be the same:
class Base {
public:
Base() : b(0) {}
int get();
virtual void sayhello() { cout << "Hello from Base with b: " << b << endl; }
protected:
virtual int getB() {return b;}
private:
int b;
};
int Base::get() {sayhello(); return getB();}
class Derived : public Base {
public:
Derived(double b_):b(b_){}
void sayhello() { cout << "Hello from Derived with b: " << b << endl; }
protected:
int getB() override {return b;} // conversion from double to int
private:
double b;
};
I'm not sure I understand you correctly, but it by "override" you mean "replace", you'd use a template:
#include <iostream>
using namespace std;
template< typename T >
class Base {
public:
Base() : b(0) {}
Base(T b_) : b(b_) {}
T get();
virtual void sayhello() { cout << "Hello from Base with b: " << b << endl; }
protected:
T b;
};
template< typename T >
T Base<T>::get() {sayhello(); return b;}
class Derived : public Base<double> {
public:
Derived(double b_):Base(b_){}
void sayhello() { cout << "Hello from Derived with b: " << this->b << endl; }
};
int main() {
Derived d(10.0);
Base<double>* b = &d;
cout << "Derived b: " << d.get() << endl;
cout << "Base b: " << b->get() << endl;
}
You code in main was also attempting Base b = d; which would lead to slicing, the above fixes that and makes sure you don't accidentially use Base<int> instead of Base<double>.
Live example
you should rewrite your Derived::ctor as follows:
Derived(double _b)
:Base(_b)
{}
And remove filed b in Derived class. Instead mark b in the Base class as protected.
EDIT
Disregard all of this
I've found a problem in your code:
Base b = d;
You're copying derived object to base. It copies only base fields. If you want polymorphism try next:
Base *b = &d;
b->get()
I have a simple code which doesn't work correctly with reference (polymorphism).
#include <iostream>
#include <string>
class Base {
public:
Base() {}
virtual ~Base() {}
virtual std::string text() const {
return "Base";
}
};
class Derived: public Base {
public:
Derived(Base& _b): b(_b) {}
virtual ~Derived() {}
virtual std::string text() const {
return b.text() + " - Derived";
}
private:
Base& b;
};
int main(int argc, char const *argv[])
{
Base b;
Derived d1(b);
std::cout << d1.text() << std::endl;
Derived d2(d1);
std::cout << d2.text() << std::endl;
return 0;
}
And output:
Base - Derived
Base - Derived
The second line in output I expected: Base - Derived - Derived. I read some resources and polymorphism work perfectly with reference and pointer but in this situation, it doesn't. If I replace reference by pointer, it work again. So, anybody can give me some explainations?
Thanks so much!
You're invoking the default copy constructor to Derived. Therefore when finished d2 will be a simple member-copy of d1, and both their b members will reference the same Base instance.
To prove this, add this to your Derived class
class Derived: public Base {
public:
Derived(Derived& d) : b(d) {}
Derived(Base& _b): b(_b) {}
virtual ~Derived() {}
virtual std::string text() const {
return b.text() + " - Derived";
}
private:
Base& b;
};
With this your output will become:
Base - Derived
Base - Derived - Derived
And just note, this is not a grand idea or a stellar learning example of polymorphism. (But it is an interesting example of construction overriding). Also note this is NOT a typical override of default copy-construction (where the parameter is a const-ref-type). Thus part of the reason this is not the greatest sample.
If you instrument the code you will see that when you call Derived d2(d1) the Derived::Derived(Base&)
constructor is not being called. This is because the d1 argument is a better match for the
implicit copy constructor, which just copies the b member from d1 to d2.
In order to see the behavior you expect, you can explicitly cast the d1 to (Base&)d1. If you do
so you will get code like the following (with the instrumentation):
#include <iostream>
#include <string>
class Base {
public:
Base() {}
virtual ~Base() {}
virtual std::string text() const {
return "Base";
}
};
class Derived: public Base {
public:
Derived(Base& _b): b(_b) {std::cout << "init'ed with: " << _b.text() << std::endl;}
virtual ~Derived() {}
virtual std::string text() const {
return b.text() + " - Derived";
}
private:
Base& b;
};
int main(int argc, char const *argv[])
{
std::cout << "Creating Base" << std::endl;
Base b;
std::cout << "Creating d1" << std::endl;
Derived d1(b);
std::cout << d1.text() << std::endl;
std::cout << "Creating d2" << std::endl;
Derived d2(d1);
std::cout << d2.text() << std::endl;
std::cout << "Creating d3" << std::endl;
Derived d3((Base&)d1);
std::cout << d3.text() << std::endl;
return 0;
}
And this gives the expected output:
Creating Base
Creating d1
init'ed with: Base
Base - Derived
Creating d2
Base - Derived
Creating d3
init'ed with: Base - Derived
Base - Derived - Derived
Your d1 and d2 both have type Derived so this is working correctly. Typically the references are reversed; e.g.
Base b;
Derived d;
Base &dr = d;
std::cout << b.text() << std::endl;
std::cout << dr.text() << std::endl;
Here text() is invoked through a Base type but the latter will call the version in Derived.
Note that it doesn't typically make sense to allow a derived class to be initialized via a base class. Suppose you add type Derived2 that has abilities or state much different from Derived. This constructor would allow
Derived2 d2;
Derived d1(d2);
which is likely a very bad idea.
As noted correctly in the comment, it is now using the default copy constructor, and that is the reason for your observation with the same output for both. So, d1 is just copied into d2 rather than used for the base member variable inside d2.
Why does the following program crash? I have a base class whose destructor is not virtual but the child class destructor is virtual:
#include <iostream>
class Base {
public:
Base() {
std::cout << "Base::Base CTOR " << std::endl;
}
~Base() {
std::cout << "Base::Base DTOR " << std::endl;
}
};
class Child : public Base {
public:
Child(){
std::cout << "Child::Child CTOR " << std::endl;
}
virtual ~Child() {
std::cout << "Child::Child DTOR " << std::endl;
}
};
int main (int argc, char **argv) {
Base *ptr = new Child;
delete ptr;
}
What you are observing is called "undefined behavior". Make Base's dtor virtual if you want do call delete on Child instance through Base pointer.
From the 2003 standard, 5.3.5/3:
In the first alternative (delete object), if the static type of the
operand is different from its dynamic type, the static type shall be a
base class of the operand’s dynamic type and the static type shall
have a virtual destructor or the behavior is undefined.
You have undefined behavior because the static type of the pointer operand to delete does not match the dynamic type of the object that it points to and you don't meet the requirements for the exception to this rule that allows passing a pointer to a base class to the object being deleted because this exception requires the base class to have a virtual destructor.
Any behaviour is possible including the code working "as expected" or a crash.
Hope this example helps you get the point:
#include <iostream>
class Base {
public:
Base() {
std::cout << "Base::Base CTOR " << std::endl;
}
~Base() {
std::cout << "Base::Base DTOR " << std::endl;
}
private:
protected:
};
class Child : public Base {
public:
Child(){
std::cout << "Child::Child CTOR " << std::endl;
}
~Child(){
std::cout << "Child::Child DTOR " << std::endl;
}
private:
protected:
};
class gChild : public Child {
public:
gChild(){
std::cout << "Child::Child gCTOR " << std::endl;
}
~gChild(){
std::cout << "Child::Child gDTOR " << std::endl;
}
private:
protected:
};
int main ( int argc, char **argv) {
Base *ptr = new gChild;
delete ptr;
}
if virtual ~Base() ,then all destructors' print gets printed.
if virtual ~child() or virtual ~gChild(),only base destructor gets printed.
It's because the destructors executes in opposite direction.and here behaviour is undefined.You must define the base destructor virtual to get the expected result.
Thanks.
Just look at this:
#include <iostream>
class Base
{
public:
void nonvirtualmethod()
{ std::cout << "Base nonvirtualmethod" << std::endl; }
virtual void virtualmethod()
{ std::cout << "Base virtualmethod" << std::endl; }
};
class Derived: public Base
{
public:
void nonvirtualmethod()
{ std::cout << "Derived nonvirtualmethod" << std::endl; }
virtual void virtualmethod()
{ std::cout << "Derived virtualmethod" << std::endl; }
};
int main()
{
Derived d;
Derived* pd = &d;
Base* pb = &d; //< NOTE: both pd and pb point to the same object
pd->nonvirtualmethod();
pb->nonvirtualmethod();
pd->virtualmethod();
pb->virtualmethod();
}
I gives you the following output:
Derived nonvirtualmethod
Base nonvirtualmethod
Derived virtualmethod
Derived virtualmethod //< invoked by a Base*
This is because there is a difference between the static type of the pb pointer (Base*)
and the dynamic type it points to (Derived).
The difference between virtual and plain methods is that non-virtual methods follow the the static type mapping (so a Base pointer invokes Base::methods), while virtual methods follow the chain of the runtime types, hence if a Base* points to a Derived, the Derived method will be called.
Destructors, in this sense, are nothing special: if it is not virtual, a Base pointer will not invoke the Derived one, hence you are left with an half-destroyed object, that is given back to the memory store.
The reason why this is UB (and not simply denied), is because the "memory store" is not managed by the language itself, but from the platform the program is hosted in: the crash most likely depends on the fact that the missing of the Derived part (still alive) will result in the operating system trying free a block of memory with a wrong starting address.