Leaking attributes of class to it's components - c++

I've got the following classes:
class A {
// Whatever
};
class B {
T attribute;
A a;
};
Now suppose i have the following scenario:
A aX, aY;
B bX, bY;
Now i can sort of "insert" aX or aY into bX or bY.
I would like for the objects of type A to know, what B they are in, or in other words, what is the "attribute" of their "superclass" B.
Question:
I would like to be able to move the objects of type A freely between their "superclasses" B and i need a way to leak the attribute of B to them dynamically at runtime, so the objects of type A always know, what B they belong to (or what is the attribute of B they are currently in).
What is the best way to do it ?

Perhaps this is useful (pointer from the owner to the attribute, and the reverse):
class A;
class B {
T attribute;
A* a;
public:
void setA(A* newA);
T getAttribute() {return attribute;}
void setAttribute() {/*some code*/}
};
class A {
B* Owner;
friend void B::setA(A* newA);
public:
void setOwner(B* newOwner) {
newOwner->setA(this);
}
};
void B::setA(A* newA)
{
A* tempA = this->a;
B* tempB = newA->Owner;
tempA->Owner = NULL;
tempB->a = NULL;
this->a = newA;
newA->Owner = this;
}
UPDATED: Fixed a bug in cycle-pointing and cycle-calling, it could be solved only with a friend function.

One thing you could to is give A a pointer to it's B "parent":
class A {
public:
A() : b_(0) {}
explicit A(B* parent) : b_(parent) {}
private:
B* b_;
};
class B {
B() : a(this) {}
};

Define "B" class as interface. Make "getAttribute" method and set pointer of "B" to "A" class's instance. Now you can make child's of "B" class and add "A" classes to them and "A" class can always know attribute of "B".
class A
{
// Whatever
B* pointerToB;
void setB(B* b){ pointerToB = b; }
};
class B
{
virtual void someMethod() = 0;
void addA(A* a)
{
a->setB(this);
this->a = *a;
}
T getAttribute(){ return attribute; }
T attribute;
A a;
};
class BB : public B {} // define BB's someMethod version or more method's

You could set a pointer to B in A and use a reference to A in B to get waht you want directly from an A object:
#include <iostream>
class B;
class A {
B *_b;
public:
void setB(B *b) {
_b = b;
}
B *getB() {
return _b;
}
};
class B {
int _attribute;
A &_a;
public:
B(A& a, int attribute) : _attribute(attribute), _a(a) {
_a.setB(this);
}
int getAttribute() {
return _attribute;
}
};
int main(int argc, const char *argv[])
{
A a1;
B b1(a1, 5);
A a2;
B b2(a2, 10);
std::cout << a1.getB()->getAttribute() << std::endl;
std::cout << a2.getB()->getAttribute() << std::endl;
return 0;
}
Output:
5
10

Related

C++ dynamic_cast on loop downcasting doesn't work as expected

I am doing a program to learn template classes and dynamic_cast uses.
It uses a template class (A) to make a list of B class pointers. On the loop, it checks for each pointer if it points to a C object, and then execute its Print() method.
The code below should output "C CALL" two times, but it only outputs "Start!". What am I missing?
#include <vector>
template<typename widget_type>
class A
{
public:
std::vector<widget_type*> value;
virtual ~A() {}
void Add(void* val)
{
widget_type* target = (widget_type*)val;
value.push_back(target);
}
};
class B
{
public:
virtual ~B() {}
};
class C : B
{
public:
void Print()
{
std::cout << "C CALL\n";
}
};
class D : B
{
};
int main()
{
std::cout << "Start!\n";
A<B>* index = new A<B>;
C* c1 = new C;
D* d1 = new D;
C* c2 = new C;
index->Add(c1);
index->Add(d1);
index->Add(c2);
for (unsigned int i = 0; i < 3; i++)
{
B* val = index->value[i];
C* target = dynamic_cast<C*>(val);
if (target)
{
target->Print();
}
}
}

Creating an initialization list of abstract base type references

I have two classes A,B which inherit from an abstract base class Abs. I would like to create an initialization list containing both of them. I would like to iterate on that list with a foreach loop.
class Abs {
public:
virtual ~Abs() = default;
virtual void f() = 0;
};
class A : public Abs {
virtual void f() override;
};
class B : public Abs {
virtual void f();
};
int main() {
A a;
B b;
const Abs& a_abs = a;
const Abs& b_abs = b;
for (const auto& abs : {a_abs, b_abs})
{
}
return 0;
}
The compilation of the for loop fails with:
error: cannot allocate an object of abstract type ‘Abs’
Why is it trying to allocate an Abs type?
How can I overcome that?
Thank you :)
there were a few things wrong with your code:
you should have a public destructor/constructor
B doesn't inherit from Abs therefore in can't be converted to Abs
i don't know if you can get what you want with references but with pointers you can. please use smart pointer this is just a prof of concept
#include <initializer_list>
#include <iostream>
class Abs {
public:
virtual ~Abs() = default;
virtual void f() const = 0;
};
class A : public Abs {
public:
virtual void f() const {
std::cout << "A" << std::endl;
}
};
class B : public Abs {
public:
virtual void f() const {
std::cout << "B" << std::endl;
}
};
int main() {
A* a = new A();
B* b = new B();
const Abs* a_abs = dynamic_cast<const Abs *>(a);
const Abs* b_abs = dynamic_cast<const Abs *>(b);
for (const auto* abs : {a_abs, b_abs})
{
abs->f();
}
delete a;
delete b;
return 0;
}

Access private members of a class instantiated using interface

I have a class derived from an interface and a friend class of the derived class. I want to access the members of derived class which is instantiated as interface. It looks like this:
Interface:
class AInterface
{
public:
virtual ~AInterface() = default;
virtual void set(int a) = 0;
};
Derived class A with friend class B:
class B;
class A : public AInterface
{
public:
~A() override {}
void set(int a) override
{
mem = a;
}
private:
friend class B;
int mem = 0;
};
class B:
class B
{
public:
B()
{
a = new A();
a->set(3);
}
int get_a()
{
// Access mem since it's a friend class
return a->mem;
}
private:
AInterface *a;
}
main:
int main()
{
B *b = new B();
std::cout << b->get_a() << std::endl;
return 0;
}
The program does not compile saying AInterface has no member named 'mem'.
Do I need getter functions in the interface and implement it in A to achieve this or is there any other way to do it?
Now work
#include <iostream>
using namespace std;
class AInterface
{
public:
virtual ~AInterface() = default;
int getMem() { return mem; }
virtual void set(int a) = 0;
protected:
int mem = 0;
};
class A : public AInterface
{
public:
~A() override {}
void set(int a) override
{
mem = a;
}
};
class B
{
public:
B()
{
a = new A{};
a->set(3);
}
int get_a()
{
// Access mem since it's a friend class
return a->getMem();
}
private:
AInterface *a;
};
int main()
{
B *b = new B();
std::cout << b->get_a() << std::endl;
return 0;
}
Method which is override by child and is pure, should be virtual.
If each class (child) Interface, variable int mem should be protected in interface.
Now works fine, like you want.
Add getter getMem()
Version with friend
#include <iostream>
using namespace std;
class AInterface
{
public:
virtual ~AInterface() = default;
virtual void set(int a) = 0;
protected:
friend class B;
int mem = 0;
};
class A : public AInterface
{
public:
~A() override {}
void set(int a) override
{
mem = a;
}
};
class B
{
public:
B()
{
a = new A{};
a->set(3);
}
int get_a()
{
// Access mem since it's a friend class
return a->mem;
}
private:
AInterface *a;
};
int main()
{
B *b = new B();
std::cout << b->get_a() << std::endl;
return 0;
}
In your class B.
class B
{
//...
int get_a()
{
return a->mem; // but a is a AInterface* !!!
}
private:
AInterface *a; // That's not an A*, but an AInterface*
};
You have 2 options.
use dynamic_cast<>
int B::get_a()
{
A* p = dynamic_cast<A*>(a);
if (p)
return p->mem;
// a is not an A*, it's another AInterface*-type object !!!
// What should you do?
throw something_or_other(); // throw?
return -1; // return an error code?
}
// or maybe add.. so you can check for errors before calling get_a()
A* B::get_A_ptr() const
{
return dynamic_cast<A*>(a);
}
dynamic_cast works fine, but can slow down your app if you need to make frequent reads of a->mem.
Store a in an A*, which is probably what you meant to do from the start...
class B
{
// ...
private:
A* a; // now a->A::mem is visible.
};
Since you explicitly call new A in B's constructor, I think option 2 is better for your case.

How do I avoid forward declarations?

Let's say I have two classes, A and B:
class B;
class A
{
private:
int an_int;
B *something_else;
public:
A(int n) : an_int(n), something_else(nullptr) {}
};
class B
{
private:
int an_int;
A *something_else;
public:
B(int n) : an_int(n), something_else(nullptr) {}
};
How can I make it so that I don't have to prototype B in order to have a pointer to a B object in class A?
This solution is most probably what is intended in an exercise about inheritance where you can't use a forward declaration.
Instead of the forward declaration
class B;
you can define an interface like
struct I_whoop
{
virtual void whoop_whoop() = 0;
};
then let class B implement that interface, and just use a pointer to the interface.
Actually You can not if using concrete class.
But You can achieve your goal by using template parameters. Making class B a template parameter of template class A.
How can I make it so that I don't have to prototype B in order to have a pointer to a B object in class A?
Like this:
class A
{
private:
int an_int;
class B *something_else;
public:
A(int n) : an_int(n), something_else(nullptr) {}
};
class B
{
private:
int an_int;
class A *something_else;
public:
B(int n) : an_int(n), something_else(nullptr) {}
};
In C and C++ it has never been necessary for a type T to be
forward declared before the declaration of objects of type T *
(or const variants), because the declaration of a T * per se requires
the compiler only to know the size of a T *, not the size or definition
of a T, and the size of a T * is the same, regardless of T.
Here is a more fleshed-out illustration:
class A
{
private:
int an_int;
class B *something_else;
public:
A(int n, class B * pb = nullptr) : an_int(n), something_else(pb) {}
int get_int() const {
return an_int;
}
void set_B(class B * pb) {
something_else = pb;
}
class B * get_B() const {
return something_else;
}
};
class B
{
private:
int an_int;
class A *something_else;
public:
B(int n, class A * pa = nullptr) : an_int(n), something_else(pa) {}
int get_int() const {
return an_int;
}
void set_A(class A * pa) {
something_else = pa;
}
class A * get_A() const {
return something_else;
}
};
#include <iostream>
int main()
{
A a(1);
B b(2);
a.set_B(&b);
b.set_A(&a);
std::cout << a.get_B()->get_int() << std::endl;
std::cout << b.get_A()->get_int() << std::endl;
return 0;
}
Output:
2
1
(gcc 4.9.2/clang 3.5.2 -std=c++11 -Wall -pedantic)

How can I do second-like constructor in c++?

I have a class A and class B, B here is a subclass of A:
class A {
public:
A(int a) : obj(a) {}
void init() {
if(magic_str == "hello") {
// do init c
c = 7;
}
}
private:
int obj;
int c;
protected:
string magic_str;
};
class B : public A {
public:
B(int a, double _b) : A(a), b(_b){}
void set_magic_str() {
magic_str = "hello";
}
private:
double b;
};
Above, the init function in A must be constructed in A, but must be called after magic_str is initialized. magic_str must be initialized in class B because there are some user-define logic.
How can I force B to invoke init in A?
To sum up, I want to split constructor code in A into two piece, and between these two piece, some user-defined behavior must be initialized in his subclass B.
One way would be to pass the magic string as an constructor to As constructor and call init in the constructor.
class A {
public:
A(int a, string m) : obj(a), magic_str(m)
{
init();
}
void init() {
if(magic_str == "hello") {
// do init c
c = 7;
}
}
private:
int obj;
int c;
protected:
string magic_str;
};
class B : public A {
public:
B(int a, double _b) : A(a,get_magic_str()), b(_b){}
static string get_magic_str() {
return "hello";
}
private:
double b;
};
Another way would be to use the builder pattern and let it handle the complex way you want your object to be created:
class A {
public:
A(int a) : obj(a) {}
void init() {
if(magic_str == "hello") {
// do init c
c = 7;
}
}
private:
int obj;
int c;
protected:
string magic_str;
};
class B : public A {
public:
static B create (int a, double _b) // <-- only allow instances to be created via this function
{
B b = B(a, _b);
b.init();
return b;
}
void set_magic_str() {
magic_str = "hello";
}
private:
B(int a, double _b) : A(a), b(_b){} //maybe protected
double b;
};
As init is a non-private member function of A, B being derived form A, can call init.
Call it after magic_string is set eg. the constructor.
A::init();
Otherwise,change A's constructor , and use this in B.
A(int a, string s)
B(int a, double _b): A (a, magic_str)...
I would change the logic to something like:
class A {
public:
A(int a) : obj(a), c(0) {}
protected:
void set_magic_str(const std::string& s) {
magic_str = s;
if (magic_str == "hello") {
// do init c
c = 7;
}
}
private:
int obj;
int c;
std::string magic_str;
};
class B : public A {
public:
B(int a, double _b) : A(a), b(_b){}
void set_magic_str() {
A::set_magic_str("hello");
}
private:
double b;
};