STL Container with iterator and inheritance - c++

Here is a sample C++ question to find out the outcome.
#include <iostream>
#include <vector>
class A
{
public:
A(int n = 0) : m_n(n) { }
public:
virtual int f() const { return m_n; }
virtual ~A() { }
protected:
int m_n;
};
class B
: public A
{
public:
B(int n = 0) : A(n) { }
public:
virtual int f() const { return m_n + 1; }
};
int main()
{
const A a(1);
const B b(3);
const A *x[2] = { &a, &b };
typedef std::vector<A> V;
V y({ a, b });
V::const_iterator i = y.begin();
std::cout << x[0]->f() << x[1]->f()
<< i->f() << (i + 1)->f() << std::endl;
return 0;
}
The output I expected was "1 4 1 4" but the correct answer is "1 4 1 3".
From above,
x[0]->f()
i.e., x[0] is nothing but a pointer to an object of type A and calling f() returns 1.
x[1]->f()
i.e., x[1] is nothing but a pointer to an object of type A (base class pointer pointing to derived class object) and calls derived class f() that returns (3 + 1) = 4
I am not sure how this behaves when we add the objects a and b into a vector container and iterating them through const_iterator with inheritance
i->f()
I can understand this as i is just a pointer to the first element i.e., object a.
But what will happen here?
(i + 1)->f()
My understanding is that it points to the next element in the sequence i.e., object b and calling f() through derived class pointer should call its member function rather than base class one's?

The vector y contains two objects of type A. Not type B. When it is constructed, it makes copies of a and b, slicing b as it does so. So (i + 1)->f() calls A::f() on that copy of the A portion of b, giving 3.

Related

Polymorphic unique_ptr class member

I would like to have a unique_ptr class member that points to the base class, but later in the constructor through polymorphism can be changed to point to a sister class that also derives from the same base class.
While I don't get any errors in the constructor setting this polymorphism, it does not seem to work correctly, since I get error messages that my polymorphic pointer can't find a member of the sister class to which I thought the pointer was now pointing.
How do I correctly achieve polymorphism here?
class A {
int bar;
};
class B : public A {
int foo;
};
class C: public A {
C();
std::unique_ptr<A> _ptr; // changing to std::unique_ptr<B> _ptr removes the "class A has no member 'foo'" error
};
C::C() : A()
{
_ptr = std::make_unique<B>(); // no errors here
int w = _ptr->foo; // class A has no member 'foo'
}
When you assign
_ptr = std::make_unique<B>();
This works because B is a derived class of A, however _ptr is still a unique_ptr to the base class. You can't change the type of a variable after it's declared.
So what are your options?
Because you know that _ptr stores a pointer to the derived class B, you can do a cast after dereferencing it:
_ptr = std::make_unique<B>();
// derefence the pointer, and cast the reference to `B&`.
B& reference_to_sister = (B&)(*_ptr);
int w = reference_to_sister.foo;
If you take this approach, you'll have to somehow keep track of which derived class is in _ptr, or you'll run the risk of running into bugs.
Alternatively, if you're using C++17, you can use std::variant:
class C : public A {
void initialize(A& a) {
// Do stuff if it's the base class
}
void initialize(B& b) {
// Do different stuff if it's derived
int w = b.foo;
}
C() {
_ptr = std::make_unique<B>(); // This works
// This takes the pointer, and calls 'initialize'
auto initialize_func = [&](auto& ptr) { initialize(*ptr); };
// This will call 'initialize(A&)' if it contains A,
// and it'll call 'initialize(B&)' if it contains B
std::visit(initialize_func, _ptr);
}
std::variant<std::unique_ptr<A>, std::unique_ptr<B>> _ptr;
};
In fact, if you use std::variant this will work even if A and B are completely unrelated classes.
Here's another short variant example
#include <variant>
#include <string>
#include <iostream>
void print(std::string& s) {
std::cout << "String: " << s << '\n';
}
void print(int i) {
std::cout << "Int: " << i << '\n';
}
void print_either(std::variant<std::string, int>& v) {
// This calls `print(std::string&) if v contained a string
// And it calls `print(int)` if v contained an int
std::visit([](auto& val) { print(val); }, v);
}
int main() {
// v is empty right now
std::variant<std::string, int> v;
// Put a string in v:
v = std::string("Hello, world");
print_either(v); //Prints "String: Hello, world"
// Put an int in v:
v = 13;
print_either(v); //Prints "Int: 13"
}

base class is a reference to another object

I just encountered a snippet of code which seems quite strange to me(see below as a minimal example), the derived::base is a reference to another object of type of base, can someone help me to answer the questions in the comments?
class base{
public:
int a;
int b;
};
class derived : public base{
public:
double c;
void run(const base & bs){
((base &) *this) = bs; // what does this line do?
// Is derived::base now a copy of bs?
// If yes, but why not write ((base) *this) = bs?
// if not, then derived::base is a reference to bs,
// then does it mean the memory of derived::base
// and members of derived are no longer contiguous?
std::cout << "a = " << a << std::endl;
}
};
PS
comments by #LightnessRacesinOrbit helped a lot to clear the questions, but I can only accept an answer post, the best is by #WhiZTiM
void run(const base & bs){
((base &) *this) = bs;
std::cout << "a = " << a << std::endl;
}
The above code can be broken down as:
void run(const base & bs){
base& base_of_this_instance = *this;
base_of_this_instance = bs;
std::cout << "a = " << a << std::endl;
}
The memory for an object of derived may be laid out as:
|| int a |x| int b |y| int c || // <- x and y represents some hypothetical padding
|| base |y| || // <- We can slice `derived` and retrieve only base
|| derived || // <- Memory consumed by derived
In your derived::run method, first, a reference to the base portion of derived is obtained, secondly that base is assigned to bs. This assignment will invoke the copy assignment operator of base. That means the base portion will now now hold a copy of whatever was in bs.
The result of
((base &) *this)
is references to base class
You can save it to a variable:
base& refToBase = ((base &) *this);
refToBase is a reference to the same object which is this
After that you have assignment
refToBase = bs;
It will assign bs's value to refToBase object
Like this:
int i = 10;
int p = 20;
int& refI = i;
int& refP = p;
refI = refP; // i == 20
p = 15; // p ==15 but i == 20
So after "strange code" from your example are executed we have the copies of bs.a and bs.b in derived::a and derived::b
the memory of derived::base and derived::c is still one batch

Access members of a class within a different class in c++

I am trying to understand object oriented programming using c++. The following is a minimal example for which the result is not what I naively expect:
#include <iostream>
class B {
public:
B (int val) : val(val) {;}
int get_val() { return val; }
int set_val(int a) { val = a; }
private:
int val;
};
class A {
public:
A (B b) : b(b) {;}
B get_b() { return b; }
private:
B b;
};
int main(){
B b_main(5);
std::cout << b_main.get_val() << std::endl; // Prints 5, which makes sense
A a_main(b_main);
std::cout << a_main.get_b().get_val() << std::endl; // Prints 5, which makes sense
a_main.get_b().set_val(2);
std::cout << a_main.get_b().get_val() << std::endl; // Why does this not print 2?
return 0;
}
The last cout statement does not make sense to me. In the second to last line, I set the value of the object to be 2, so why does this not print 2? Looking at some similar questions on Stack Exchange, I found some suggestions to make A and B be friends of each other. I tried adding friend class A in class B and friend class B in class A, but this did not work. In my understanding, adding the friend statements should be unnecessary since I have the get_b() method in class A. I found some suggestions to try passing the object of type B in by reference to the constructor of A: A (B& b) : b(b) {;} but this did not work either.
Can anyone explain to me why the program is not producing the intended result and also how to obtain the desired result (that is, the last cout statement prints 2)?
Note: I also experimented with the following. I made the private variable b of class A be public:
#include <iostream>
class B {
public:
B (int val) : val(val) {;}
int get_val() { return val; }
int set_val(int a) { val = a; }
private:
int val;
};
class A {
public:
A (B b) : b(b) {;}
B b; // This is now public
//B get_b() { return b; } // This is no longer needed
private:
};
int main(){
B bmain(5);
std::cout << bmain.get_val() << std::endl;
A amain(bmain);
std::cout << amain.b.get_val() << std::endl;
amain.b.set_val(2);
std::cout << amain.b.get_val() << std::endl; // Works!
return 0;
}
And now I obtain the desired result. Is this how the code should be implemented as opposed to the first code snippet? I would like to have a get_b() method as in the first code snippet, but if this is not the correct way of going about this, please let me know.
In the second to last line, I set the value of the object to be 2, so why does this not print 2?
Because you return a copy of the B object in a_main with the get_b() method. What happens is that the b variable in a_main is copied, i.e. another object of class B, identical to the b member, is created, and returned to the caller. Then, that new B object is modified. But it has no connection to the original b in a_main. This has little to do with visibility and member access.
However, in the second example, you expose the b member in a_main and directly operate on that object without making a copy of it, thus the successful result. What the public modifier changes is that it allows you to access the b object directly, hence the effect.
I found some suggestions to try passing the object of type B in by reference to the constructor of A: A (B& b) : b(b) {;} but this did not work either.
That isn't going to work. What happens when you do so, is that the A::b is initialized using the value that is passed by reference, true. But the reference only leads to no additional copy of b passed to the constructor being made. This reference does not create a link between the b passed to the constructor and A::b. It's on the other end, so to say.
By the way, A (B& b) : b(b) {;} that the c'tor parameter name is identical to the member name is a bad practice. It's a good idea to have them named similarly, but still, add e.g. an underscore: A (B& _b) : b(_b) {;}
If you want to achieve the same result in the first snippet, return a reference to b like so:
B& get_b() { return b; }
Still, this is undesirable, because you expose a private member of class A just to allow clients of A to modify a certain property of that member. Better provide a method in A to set the val property of A::b without giving full access to A::b.
Definitely see this: What's the difference between passing by reference vs. passing by value?
and maybe this: Java and C++ pass by value and pass by reference
because I have a feel that you're coming from Java and expect pass-by-reference in C++ by default.
get_b returns a copy of your private variable b, not the actual variable. If you want to be able to access it, you need to return a reference to b so that the returned value can be manipulated. Your get_b definition should look like this:
B& get_b() { return b; }
if that is what you expect to do. However, this is not usually a desirable solution. If you are going to be actively changing the value of b you should write a set_b function to manipulate the variable. And if you are really working with the variable a lot, reading and writing values to it, you should keep it public for fast access.
Just for the sake of completeness, you can solve this problem as a C programing problem rather than using all the fancy references in C++ programing. When you get b_main from a_main, the returned object does not occupy the same memory address.
#include <iostream>
class B {
public:
B (int val) : val(val) {;}
int get_val() { return val; }
int set_val(int a) { val = a; }
private:
int val;
};
class A {
public:
A (B b) : b(b) {;}
B get_b() { return b; }
private:
B b;
};
int main(){
B b_main(5);
B* addrb = &b_main;
std::cout << b_main.get_val() << std::endl; // Prints 5, which makes sense
std::cout<<"Address of b_main: "<<addrb<<std::endl;
A a_main(b_main);
B bt = a_main.get_b();
addrb = &(bt);
std::cout << a_main.get_b().get_val() << std::endl; // Prints 5, which makes sense
std::cout<<"Address of a_main.get_b(): "<<addrb<<std::endl;
a_main.get_b().set_val(2);
std::cout << a_main.get_b().get_val() << std::endl; // Why does this not print 2?
return 0;
}
Notice the difference in address of the new cout statements. One way to fix this is to return pointers rather than b itself. i.e.
#include <iostream>
class B {
public:
B (int val) : val(val) {;}
int get_val() { return val; }
int set_val(int a) { val = a; }
private:
int val;
};
class A {
public:
A (B b) : b(b) {;}
B* get_b() { return &b; }
private:
B b;
};
int main(){
B b_main(5);
//B* addrb = &b_main;
std::cout << b_main.get_val() << std::endl; // Prints 5, which makes sense
//std::cout<<"Address of b_main: "<<addrb<<std::endl;
A a_main(b_main);
//B bt = a_main.get_b();
//addrb = &(bt);
std::cout << a_main.get_b()->get_val() << std::endl; // Prints 5, which makes sense
//std::cout<<"Address of a_main.get_b(): "<<addrb<<std::endl;
a_main.get_b()->set_val(2);
std::cout << a_main.get_b()->get_val() << std::endl; // Why does this not print 2?
return 0;
}

c++ Classes and their layouts and conversions

I was given this code to test my cpp understanding, and I am quite confused:
#include "stdafx.h"
#include <iostream>
#include <cstddef>
using namespace std;
class A
{
public:
A() : m_x(0) { }
public:
static ptrdiff_t member_offset(const A &a)
{
const char *p = reinterpret_cast<const char*>(&a);
const char *q = reinterpret_cast<const char*>(&a.m_x);
return q - p;
}
private:
int m_x;
};
class B
: public A
{
public:
B() : m_x('a') { }
public:
static int m_n;
public:
static ptrdiff_t member_offset(const B &b)
{
const char *p = reinterpret_cast<const char*>(&b);
const char *q = reinterpret_cast<const char*>(&b.m_x);
return q - p;
}
private:
char m_x;
};
int B::m_n = 1;
class C
{
public:
C() : m_x(0) { }
virtual ~C() { }
public:
static ptrdiff_t member_offset(const C &c)
{
const char *p = reinterpret_cast<const char*>(&c);
const char *q = reinterpret_cast<const char*>(&c.m_x);
return q - p;
}
private:
int m_x;
};
int _tmain(int argc, _TCHAR* argv[])
{
A a;
B b;
C c;
std::cout << ((A::member_offset(a) == 0) ? 0 : 1);
std::cout << ((B::member_offset(b) == 0) ? 0 : 2);
std::cout << ((A::member_offset(b) == 0) ? 0 : 3);
std::cout << ((C::member_offset(c) == 0) ? 0 : 4);
std::cout << std::endl;
return 0;
}
The answer is 0204.
I have understand the first 3cases, but not the last one. The difference between the last and first is a virtual desctructor. Is this related? If yes, how?
The code example has an implementation defined behavior. The output for any of the cases cannot be guaranteed. It is not guaranteed that members of a class are always placed in contiguous memory locations.There can be padding bytes added in between them. And whether or not padding is added is left out as an implementation detail. Your suspicion of virtual playing a role just might be true[Note 1:]. But the important thing to note is even without the virtual the output is not guaranteed.
Reference:
C++11: 9.2 Class members [class.mem]
14) Nonstatic data members of a (non-union) class with the same access control (Clause 11) are allocated so
that later members have higher addresses within a class object. The order of allocation of non-static data
members with different access control is unspecified (11). Implementation alignment requirements might
cause two adjacent members not to be allocated immediately after each other; so might requirements for
space for managing virtual functions (10.3) and virtual base classes (10.1).
[Note 1]:
Dynamic dispatch itself is a implementation defined mechanism but most(read all known) implementations use the virtual table and pointer mechanism to implement it.
In case of a polymorphic class(which does not derive from any other class) usually the virtual pointer is stored as the first element of class. So it is reasonable to assume that this is what happens behind the scenes in the last case when you run the code sample on your environment.
Online sample:
#include<iostream>
using std::cout;
using std::endl;
class B;
typedef void (*HANDLE_DOSOMETHING)(B *const, int q);
class B
{
public:
virtual void doSomething(int q)
{
std::cout<<"B::doSomething()"<<q<<endl;
}
void dummy()
{
HANDLE_DOSOMETHING *f1ptr = NULL;
int *vtbl = NULL;
int *vptr = (int *)this; // address of the object
vtbl = (int *)*vptr; //address of the VTABLE
f1ptr = (HANDLE_DOSOMETHING *)&(vtbl[0]); //address of the 1st virtual function
(*f1ptr)(this, 55);
}
};
int main()
{
B objb;
objb.dummy();
return 0;
}
Output:
B::doSomething()55
Yes, the virtual member function(s) (in this case a destructor) are held in a "vtable", which is often stored as the first element(s) of the class data structure.
However, be aware that there is no strict rules in the C++ standard that says that this is the case.

Pointing a variable to a member function from a different class type

In C++, how do i call a method member of class A from a class B, using a pointer? By the way Class A and B are of different types.
I read that when a pointer is pointing to member function it can only point member functions within the class. But how can i point to a member function outside the class?
for example:
class A
{
public:
int add(int x)
{
return x+x;
}
};
int main()
{
typedef int (A::*pointer)();
pointer func = &A::add;
A objt;
B objt2;
obt2.*func(2);// the compiler give me an error of incompatible with object type ‘B’
return 0;
}
I think you can run it as follows:
(*func)(&objt, 2)
Better choice would be to use boost::bind/boost::function instead:
boost::function<int(int)> func = boost::bind(&A::add, &objt, _1);
func(2);
I just noticed that you're trying to make it run as if it were a method of class B.
It's completely nonsensical, but if you don't care about correctness and like to live dangerously with completely unpredictable results, it's easier to do this:
((A *) &objt2)->add(2);
If B uses A (calls some A's member) then B depends on A and you can implement this by simply providing B with pointer to A through which it can call A's methods - see class B1 below in the code.
You can wrap the call of A's member into a separate object - functor. You can create generic solution by implementing it as a template class and providing address of the object A, address of the method and argument. For this, see implementation of class B2.
class A
{
public:
int add(int x)
{
return x+x;
}
};
typedef int (A::*MEMFN)(int);
class B1
{
public:
void InvokeAAdd(A* pA, int x)
{
cout << "result = " << pA->add(x) << endl;
}
};
template<class T, typename TMemFn, typename TArg, typename TRetVal>
class B2
{
T* pT;
TMemFn memFn;
TArg arg;
public:
B2(T* pT, TMemFn memFn, TArg arg) :
pT(pT), memFn(memFn), arg(arg){}
TRetVal operator()()
{
return (pT->*memFn)(arg);
}
};
int main()
{
A a;
B1 b;
b.InvokeAAdd(&a, 2);
B2<A, MEMFN, int, int> b2(&a, &A::add, 2);
cout << "result (via functor) = " << b2() << endl;
return 0;
}
Output:
result = 4
result (via functor) = 4