Output of this program is "Method B". How can an instance of the parent object call the child class's function through a static_cast?
To make things more confusing, if I make method() virtual, then this code outputs "Method A".
Can anyone explain what is happening here?
class A {
public:
void method() {
cout << "Method A" << endl;
}
};
class B : public A {
public:
void method() {
cout << "Method B" << endl;
}
};
int main() {
A a;
B* bptr = static_cast<B*>(&a);
bptr->method();
}
Related
This is purely a theoretical question. I don't have a particular use case in mind.
Can the virtuality of a C++ function be suppressed somewhere down the class hierarchy, or is it that once a virtual function is defined in a base class, it remains virtual down the rest of its class hierarchy?
I wrote some sample code where I was attempting to suppress the virtuality of a method defined up the class hierarchy but I did not succeed. My sample code follows:
class Base {
public:
virtual void myFunc() {
std::cout << "myFunc in Base" << std::endl;
}
};
class Child : public Base {
public:
void myFunc() {
std::cout << "myFunc in Child" << std::endl;
}
};
class GrandChild : public Child {
public:
void myFunc() {
std::cout << "myFunc in GrandChild" << std::endl;
}
};
int main() {
Base* ptr = new GrandChild();
ptr->myFunc();
return 0;
}
The output is as follows:
myFunc in GrandChild
One thing you can do is create a member with a different signature (even using defaulted arguments).
That is:
struct Base
{
virtual void foo()
{
std::cout << "Base::foo" << std::endl;
}
};
struct Derived : Base
{
void foo(int = 0)
{
std::cout << "Derived::foo" << std::endl;
}
};
...
Base * ptr = new Derived;
ptr->foo(); // will invoke Base::foo()
for which reason this program:
#include <iostream>
using namespace std;
class Base {
public:
Base() { cout << "Costruttore Base" << endl; }
virtual void foo(int) { cout << "Base::foo(int)" << endl; }
virtual void bar(int) { cout << "Base::bar(int)" << endl; }
virtual void bar(double) { cout << "Base::bar(double)" << endl; }
virtual ~Base() { cout << "Distruttore Base" << endl; }
};
class Derived : public Base {
public:
Derived() { cout << "Costruttore Derived" << endl; }
void foo(int) { cout << "Derived::foo(int)" << endl; }
void bar(int) const { cout << "Derived::bar(int)" << endl; }
void bar(double) const { cout << "Derived::bar(double) const" << endl; }
~Derived() { cout << "Distruttore Derived" << endl; }
};
int main() {
Derived derived;
Base base;
Base& base_ref = base;
Base* base_ptr = &derived;
Derived* derived_ptr = &derived;
cout << "=== 1 ===" << endl;
base_ptr->foo(12.0);
base_ref.foo(7);
base_ptr->bar(1.0);
derived_ptr->bar(1.0);
derived.bar(2);
return 0;
}
In the call base_ptr->bar(1.0); is called Base::bar(double), instead in the derived_ptr->bar(1.0); is called Derived::bar(double) const.
I understood that is about the const keyword, but I don't understand why the compiler is choosing different overloaded functions.
If I remove the const keyword, everything is working as expected, calling in both cases the Derived::bar
That's because const changes the signature of the function, so they're different. Either make both the base class and derived class const or not, otherwise one won't override the other.
It's because you're not really overriding the function bar(). You are defining a new function bar() in the derived class with a different signature.
So either remove the const in the derived class or add a const to the signature of bar() in the upper class. (Or keep it as it is but know that you now have two functions named bar() in derived class, one of which is hidden)
C++11 added the override specifier to prevent these kind of surprises. Use, the override keyword, and the compiler will only compile your code, if it does override.
Taking the supposedly override of bar(int) (this also applies to the bar(double):
class Base {
public:
....
virtual void bar(int) { cout << "Base::bar(int)" << endl; }
};
class Derived : public Base {
public:
...
//This isn't an override, program is well formed
void bar(int) const { cout << "Derived::bar(int)" << endl; }
};
The bar member function in Derived did not override the base class' own. Because the const qualifications are different, hence the member function signatures are different. All you did in the derived class was to add a new overload and hide that of the base class'.
Add the override keyword in the derived class' and the compiler will give a diagnostic if it doesn't override.
class Base {
public:
....
virtual void bar(int) { cout << "Base::bar(int)" << endl; }
};
class Derived : public Base {
public:
...
//This isn't an override, program is ill-formed, diagnostic required
void bar(int) const override { cout << "Derived::bar(int)" << endl; }
};
To override, the member function signatures must be the same.
class Base {
public:
....
virtual void bar(int) { cout << "Base::bar(int)" << endl; }
};
class Derived : public Base {
public:
...
//This overrides
void bar(int) override { cout << "Derived::bar(int)" << endl; }
};
So, learn to use the override keyword whenever you want to override, it will save you some headaches.
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
Let's say I have a base class and a derived class:
struct A
{
void foo()
{
std::cout << "Do one thing." << std::endl;
}
};
struct B: public A
{
void foo()
{
std::cout << "Do another thing." << std::endl;
}
};
B myB;
myB.foo();
Normally this would print Do another thing., but what if I wanted foo() to also run the base foo() and print:
Do one thing.
Do another thing.
Call A::foo() in B::foo(), that way the base class's function will execute first, then the rest of the derived class function executes after that.
struct A
{
void foo()
{
std::cout << "Do one thing." << std::endl;
}
};
struct B : public A
{
void foo()
{
A::foo();
std::cout << "Do another thing." << std::endl;
}
};
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()