I have a Base
class, which is then inherited by Foo
, and Foo
is in turn inehrited by Bar
.
Here is the header file base.h
for my Base
class:
#pragma once
class Base {
public:
void runExample();
private:
virtual void print();
};
And the implementation base.cpp
:
#include "base.h"
void Base::runExample() {
print();
}
void Base::print() {};
Here is the header file foo.h
for my Foo
class:
#pragma once
#include "../base/base.h"
class Foo : public Base {
public:
Foo();
private:
void print();
const char* toPrint;
};
And the implementation foo.cpp
:
#include "foo.h"
Foo::Foo() {
toPrint = "Hello Foo";
}
void Foo::print() {
std::cout << toPrint << std::endl;
}
Here is the header file bar.h
for my Bar
class:
#pragma once
#include "../foo/foo.h"
class Bar : public Foo {
public:
Bar();
private:
const char* toPrint; // "overrides" toPrint from parent class Foo?
};
And the implementation bar.cpp
:
#include "bar.h"
Bar::Bar() {
toPrint = "Hello Bar";
}
And finally, my main function:
#include "../bar/bar.h"
int main() {
Bar bar = Bar();
bar.runExample();
}
So, I have this kind of relationship between the classes:
Bar
is a Foo
which is a Base
.
What I was expecting to see in the output was "Hello Bar", but what I actually see is "Hello Foo".
If I "override" the print
method declared in Foo
in Bar
to print toPrint
then I get the expected result, however this seems to break the point of inheritance; i.e. why would I need to re-define the functionality when it's already defined.
What I am expecting is that when Bar.print()
is invoked, it uses Foos
implementation, but the actual field toPrint
has been "replaced" with the value inside the Bar
implementation.
I am very new to C , and I'm coming from a Kotlin background. Forgive me if this is like C 101 basics, but I'm pretty confused as to why this is happening. Could anyone point me in the right direction?
CodePudding user response:
In C , data members cannot be "overridden" as you expect, and a reference to toPrint
will not be dynamically bound to equally named data members in subclasses.
With
class Bar : public Foo {
...
const char* toPrint; // "overrides" toPrint from parent class Foo?
};
you introduce a member variable Bar::toPrint
next to Foo::toPrint
, which is inherited. The code
void Foo::print() {
std::cout << toPrint << std::endl;
}
will always stick to the toPrint
-member in his scope, i.e. to Foo::toPrint
.
The following code illustrates this behaviour:
struct Base {
const char* toPrint = "Base";
virtual void print() const { cout << toPrint << std::endl; }
};
struct Derived: public Base {
const char* toPrint = "Derived";
void printBoth() const { cout << "own:" << toPrint << "; inherited: " << Base::toPrint << std::endl; }
};
int main() {
Derived d;
cout << "call inherited method print:" << std::endl;
d.print();
cout << "call method printBoth, showing both data members:" << std::endl;
d.printBoth();
}
Output:
call inherited method print:
Base
call method printBoth, showing both data members:
own:Derived; inherited: Base