Why does `this` have different addresses in subclasses? - c++

Why does the d instance have different this addresses? Someone told me that in OOP languages, a derived class is simply all the members of the base class, followed by members of its own.
#include <iostream>
#include <memory>
struct A
{
int member;
};
struct B : public virtual A
{
void print_b() { std::cout << static_cast<void*>(this) << " " << static_cast<void*>(&this->member) << std::endl; }
};
struct C : public virtual A
{
void print_c() { std::cout << static_cast<void*>(this) << " " << static_cast<void*>(std::addressof(member)) << std::endl; }
};
struct D : public B, public C
{
void print()
{
print_b();
print_c();
}
};
int main()
{
D d;
d.print();
}
Online outputs:
0x700af9347b90 0x700af9347ba0
0x700af9347b98 0x700af9347ba0

Because the B and C base sub objects are distinct objects in relation to each other and cannot share an address.
Empty base sub objects could be exempted from the requirement of having a unique address, but B and C are not empty.

Related

How to initialize member variables before inherited classes

I'm trying to make one class which requires member variables to be initialized first. I know why this happens, but is there a way around this?
Current print order:
second
first
Wanted print order:
first
second
#include <iostream>
struct A {
A() {
std::cout << "first" << '\n';
}
};
struct B {
B() {
std::cout << "second" << '\n';
}
};
struct C : public B {
C() : a(), B() {
}
A a;
};
int main() {
C c;
return 0;
}
Stick your members that need initializing first in a struct and inherit privately from that, before B.
struct A {
A() { std::cout << "first" << '\n'; }
};
struct B {
B() { std::cout << "second" << '\n'; }
};
struct Members { A a; };
struct C : private Members, public B {
C() : Members(), B() {}
};
int main() {
C c;
}
The downside with this is that there is no way to avoid exposing the "member struct" to the outside world, but that shouldn't be a problem in practice.
In C++ base classes will be initialized before any member variables of a derived class.
The best recourse given the information you've provided is to prefer composition over inheritance:
struct A {
A() {
std::cout << "first" << '\n';
}
};
struct B {
B() {
std::cout << "second" << '\n';
}
};
struct C {
A a;
B b;
};
This will exhibit the desired behavior
Make A a needed reference for C:
#include <iostream>
struct A {
A() {
std::cout << "first" << '\n';
}
};
struct B {
B() {
std::cout << "second" << '\n';
}
};
struct C : public B {
C(const A& a) : _A(a), B() {}
const A& _A;
};
int main() {
A a;
C c(a);
return 0;
}

Addresses in C++ of diamond inherited classes

Can somebody explain me why the address of an object changes when I cast it to an other parent class type in an diamond inherited class structure?
See this example:
#include <iostream>
class A{
public:
A(){};
virtual int a(){
return 0;
};
};
class B: virtual public A{
public:
B(){};
};
class C: virtual public A{
public:
C(){};
};
class D: public B, public C{
public:
D(){};
};
int main(){
A* a = new D();
std::cout << "dynamic_cast<A*>: " << dynamic_cast<A*>(a) << std::endl;
std::cout << "dynamic_cast<B*>: " << dynamic_cast<B*>(a) << std::endl;
std::cout << "dynamic_cast<C*>: " << dynamic_cast<C*>(a) << std::endl;
std::cout << "dynamic_cast<D*>: " << dynamic_cast<D*>(a) << std::endl;
return 0;
}
The output is:
dynamic_cast<A*>: 0x11e3c20
dynamic_cast<B*>: 0x11e3c20
dynamic_cast<C*>: 0x11e3c28
dynamic_cast<D*>: 0x11e3c20

How does an inherited member function in C++ work with children member variable?

For instance, I have base class A:
class A {
public:
callA() {
val = 100;
std::cout << this->val << std::endl;
}
int val;
}
class B : public A {
public:
B() {
val = 10;
}
int val;
}
B b;
b.callA();
What will b.callA() print?
And for B inheriting A, if B does not have a field val, will B share an exact reference to A's val, or is it a copy?
Internally, any instance of Class B contains an entire copy of Class A. In fact, when you initialize a new instance of Class B, Class A's constructor is run first. Therefore, when you call a non-virtual function from the base class, it will run as if it were run from the base class, which is internal to the derived class. It can even access the private variables of the base class (which the derived class wouldn't be able to access, it only has access to public/protected variables from the base class).
Example:
#include <iostream>
using namespace std;
class A
{
public:
A()
{
cout << "Base constructor!" << endl;
privateVar = 10;
}
void testPrint()
{
cout << "privateVar: " << privateVar << endl;
}
private:
int privateVar;
};
class B : public A
{
public:
B()
{
cout << "Derived Constructor!" << endl;
}
};
int main()
{
B testB;
testB.testPrint();
return 0;
}

Override member field in derived classes

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()

virtual function redefinition hides other overloaded functions of same name from another base class

Ok, I'm using virtual functions, overloaded functions, and multiple inheritance. Of course this doesn't turn out well.
The scenario: Class base1 has a virtual function that needs to be specified by its child.
Class derived derives from two parents base1 and base2, and should use base2's existing functionality to define base1's virtual function.
This is ok, but awkward of course. The motivation is I cannot change the class base2 and the existing interface already heavily invested in has base1 and base2 class functions of the same name. This is ok, nothing is implemented in base1, it should just redirect to base2.
My problem arises because base2 has several overloaded functions of the same name as the virtual function in question. All of the other overloaded versions become essentially hidden at compile time.
Here's a small demonstration code.
// this version does not compile, overloaded samenameFunc(int, int) cannot be found in the derived class.
#include <iostream>
using namespace std;
class base1 {
public:
virtual void samenameFunc(int scratch) { cout << "from base1: " << scratch << std::endl; }
};
class base2 {
public:
void samenameFunc(int scratch) { cout << "samenameFunc from base2: " << scratch << std::endl; }
void samenameFunc(int scratch, int foo) { cout << "samenameFunc(2 args) from base2: " << scratch << ", " << foo << std::endl; }
};
class derived : public base1, public base2 {
public:
void samenameFunc(int scratch) { base2::samenameFunc(scratch); }// { cout << "from derived: " << scratch << std::endl; }
};
int main()
{
derived d;
d.samenameFunc(66);
d.samenameFunc(77, 88);
return 0;
}
And the compiler errors:
$ g++ inheritance_overload_tester.cc
inheritance_overload_tester.cc: In function ‘int main()’:
inheritance_overload_tester.cc:26: error: no matching function for call to ‘derived::samenameFunc(int, int)’
inheritance_overload_tester.cc:18: note: candidates are: virtual void derived::samenameFunc(int)
If the overloaded samenameFunc(int, int) is renamed, I can compile and function as expected. But remember, I can't actually change base2.
// this version does compile
#include <iostream>
using namespace std;
class base1 {
public:
virtual void samenameFunc(int scratch) { cout << "from base1: " << scratch << std::endl; }
};
class base2 {
public:
void samenameFunc(int scratch) { cout << "samenameFunc from base2: " << scratch << std::endl; }
void anotherFunc(int scratch, int foo) { cout << "anotherFunc(2 args) from base2: " << scratch << ", " << foo << std::endl; }
};
class derived : public base1, public base2 {
public:
void samenameFunc(int scratch) { base2::samenameFunc(scratch); }// { cout << "from derived: " << scratch << std::endl; }
};
int main()
{
derived d;
d.samenameFunc(66);
d.anotherFunc(77, 88);
return 0;
}
If this can't be fixed in the existing presentation, can someone suggest a different object inheritance model to solve my problem?
In the definition of the derived class, you can add a using declaration to make the function from base2 visible:
using base2::samenameFunc;