How to expose a member objects interface in C++ - c++

C++ : I have a basic object (object A) that contains a member object (object B). The member object interface (object B) needs to be fully exposed through the pointer to object A. What's the best way to do this? I could place the object as a public member but this feels like a hack. I could write wrappers for all B's interface in A but this feels ugly. I could merge the objects but I am doing class serialization to XML so having distinct classes is cleaner. I thought about friend classing but I don't think that applies to this situation.
What is the standard way to resolve this type of issue?

Let B implement an interface IB. A manages an instance of B internally and has a getter getB that returns the IB interface of the private B instance. If you want to protect the B instance, you can make the IB methods const and also hide the destructor (by making it private in IB).
class IB {
private:
~IB();
public:
virtual void method1() = 0;
virtual void method2() = 0;
};
class B : public IB {
public:
virtual void method1() {};
virtual void method2() {};
void destruct() { delete this; }
};
class A {
private:
B myB;
public:
IB *getB() { return &myB; }
};
(This is just to give an idea. It's been 3+ years since I last touched C++. I could have made some blatant errors.)

I reject the notion that doing this at all is a good idea, but I would make it a public member. If you don't like that you can have a getB() method. If possible, I would make it return a const reference instead of a normal reference.

Overload the -> operator in A and in the implementation return the pointer variable of type B.
But as you know you will not be able to access A's members through A's pointer and ->. Also it has the risk of causing confusion who ever read the code.
I meant something like this.
struct A
{
B *p;
B * operator -> ()
{
return p;
}
};

Related

Protected member is not accessible through a pointer or object [duplicate]

Can someone explain why this code doesn't work.
class A
{
public:
A(void){}
virtual ~A(void){}
protected:
A* parent;
};
class B : public A
{
public:
B(void){parent = new B;}
~B(void){delete parent;}
protected:
int a;
};
class C : public B
{
public:
C(void){}
virtual ~C(void){}
void f(void){ ((B*)parent)->a; }
};
How is it possible that C isn't able to access members of B?
If I convert parent to a C* in stead of a B* it works fine. But I don't want users to take any unnecessary risks. Is there a cleaner way access a?
Thanks.
From an object of the C class, you can access protected members of B, but only if they're part of some object of class C (maybe yours, maybe not). In other words, to access a from C, you need a pointer (or a reference) to C. This is what the protected modifier means.
The reason for this is the following. The ((B*)parent) pointer may point to some other subclass of B, completely different from C, and that subclass may have the a member inaccessible.

overriding with difference access specification c++

I came across a question while taking iKM test. There was a base class with two abstract methods with private access specifier. There was a derived class which was overriding these abstract methods but with protected/public access specifier.
I never came across such thing where overridden methods in derived class had different access specification. Is this allowed ? If yes, does it comply to "IS A" relation between base and derived (i.e. safely substitutable).
Could you point me to some references which can provide more details on such usages of classes ?
Thank you.
It is allowed, in both directions (ie, from private to public AND from public to private).
On the other hand, I would argue it does not break the IS-A relationship. I base my argument on 2 facts:
using a Base& (or Base*) handle, you have exactly the same interface as before
you could perfectly (if you wish) introduce a forward method that is public and calling the private method directly anyway: same effect with more typing
Yes, this is legal, accessibility is checked statically (not dynamically):
class A {
public:
virtual void foo() = 0;
private:
virtual void bar() = 0;
};
class B : public A {
private:
virtual void foo() {} // public in base, private in derived
public:
virtual void bar() {} // private in base, public in derived
};
void f(A& a, B& b)
{
a.foo(); // ok
b.foo(); // error: B::foo is private
a.bar(); // error: A::bar is private
b.bar(); // ok (B::bar is public, even though A::bar is private)
}
int main()
{
B b;
f(b, b);
}
Now, why would you want to do that? It only matters if you use the derived class B directly (2nd param of f()) as opposed to through the base A interface (1st param of f()).
If you always use the abstract A interface (as I would recommend in general), it still complies to the "IS-A" relashionship.
As many of the guys pointed out it is legal.
However, "IS-A" part is not that simple. When it comes to "dynamic polymorphism" "IS-A" relation holds, I.e. everything you can do with Super you can also do with Derived instance.
However, in C++ we also have something that is often referred as static polymorphism (templates, most of the time). Consider the following example:
class A {
public:
virtual int m() {
return 1;
}
};
class B : public A {
private:
virtual int m() {
return 2;
}
};
template<typename T>
int fun(T* obj) {
return obj->m();
}
Now, when you try to use "dynamic polymorphism" everything seems to be ok:
A* a = new A();
B* b = new B();
// dynamic polymorphism
std::cout << a->m(); // ok
std::cout << dynamic_cast<A*>(b)->m(); // ok - B instance conforms A interface
// std::cout << b->m(); fails to compile due to overriden visibility - expected since technically does not violate IS-A relationship
... but when you use "static polymorphism" you can say that "IS-A" relation no longer holds:
A* a = new A();
B* b = new B();
// static polymorphism
std::cout << fun(a); // ok
//std::cout << fun(b); // fails to compile - B instance does not conform A interface at compile time
So, in the end, changing visibility for method is "rather legal" but that's one of the ugly things in C++ that may lead you to pitfall.
Yes, this is allowed as long as the signature is the same. And in my opinion, yes, you're right, overriding visibility (for example, public -> private) breaks IS-A. I believe Scott Myers Effective C++ series has a discussion on this one.

Cast member of virtual base class

I know that this code won't work and I also know why, but is there an alternative?
class A
{
public:
A(void){}
virtual ~A(void){}
protected:
A* parent;
int a;
};
class B : public virtual A
{
public:
B(void){}
virtual ~B(void){}
protected:
void f(){ ((B*)parent)->a; }
};
It is not possible to cast parent to a B*, since A is a virtual base class. Not casting parent also gives an error. I hope I don't have to make all members public. Does someone have an idea how to access A::a?
Edit
Using friends doesn't work, since classes derived from B don't have access to A::a.
Some options:
Make a public
Create a public setter/getter method for a -
make B a friend of class A (or just the function f())
The 3rd option his works better than the other 2 if you want to allow only A (or a specific function) to have access to members of A. On the other hand with the other 2 options you can make only that member public (but it will be public to everyone)
Making an answer from my comment above because I tested it and it compiles fine.
Without the cast, it probably fails because you are trying to access a protected field of A in B. You can just add a public getter and remove the cast to B*
class A
{
public:
A(void){}
virtual ~A(void){}
int getA() { return a; }
protected:
A* parent;
int a;
};
class B : public virtual A
{
public:
B(void){}
virtual ~B(void){}
protected:
void f(){ (parent)->getA(); }
};
This works:
class A {
public:
A(void){}
virtual ~A(void){}
protected:
A* parent;
int a;
int parent_a(){ return parent->a;}
};
class B : public virtual A
{
public:
B(void){}
virtual ~B(void){}
protected:
void f(){ A::parent_a(); }
};
Note that:
a doesn't get exposed to the outside world,
the retrieved a is necessary the correct one, since B inherit virtually from A, so a successful dynamic cast of parent to B before getting its a field should return the same one as the solution offered above.
Now, why does this work?
Because a class is implicitely friend of itself.
That's what dynamic_cast is for. If you don't want to redesign your code, just replace the C-style cast with a dynamic_cast:
void f() { dynamic_cast<B*>(parent)->a; }
For this to work correctly, A must have at least one virtual function (as this one does). In addition, the cast will produce a null pointer if parent does not, in fact, point to an object of type B.
class B : public virtual A
{
public:
B(void){}
virtual ~B(void){}
protected:
void f(){ this->a; }
};
you're allowed to access protected member from parent class (A mother class of B).
I think the problem here is not so much how to access the element a, but why you need a tree of diamond hierarchies in your design. You should at first step back and evaluate if you really need a tree of diamonds.
If you do, then instead of your current approach, provide A with a nice appropriate (public) abstract interface that can be called from B. When you start accessing parent protected attributes directly you tightly couple components, making it easy to break your code and making it very hard to change your design later in the application's lifespan.
Thanks everyone, some usable possibilities were mentioned, like using friends and creating additional functions for each variable. This could work in some scenarios, but not in my case. Adding each derived class as a friend has the problem that it makes the library less user friendly when they want to add a class. Adding functions per variable would add over hundred extra functions for some classes.
What I did as my final solution was creating a copy instead of a cast. Though it will run a little bit slower, the code will remain clean. To counter the speed problem. Accessing local variables is a lot faster than accessing global variables.
This is how it looks now:
class A
{
public:
A* parent;
virtual ~A(void){}
virtual A & operator = (const A & x)
{
a = x.a;
parent = x.parent;
return *this;
}
protected:
int a;
};
class B : public virtual A
{
public:
B(void){}
virtual ~B(void){}
using A::operator =;
virtual B & operator = (const B & x)
{
A::operator = (x);
return *this;
}
void f(void)
{
B p;
p = *parent;
int x = p.a;//Allowed.
}
};
If you have a better solution, please feel free post it.

access protected inherited member with pointer to base class

Can someone explain why this code doesn't work.
class A
{
public:
A(void){}
virtual ~A(void){}
protected:
A* parent;
};
class B : public A
{
public:
B(void){parent = new B;}
~B(void){delete parent;}
protected:
int a;
};
class C : public B
{
public:
C(void){}
virtual ~C(void){}
void f(void){ ((B*)parent)->a; }
};
How is it possible that C isn't able to access members of B?
If I convert parent to a C* in stead of a B* it works fine. But I don't want users to take any unnecessary risks. Is there a cleaner way access a?
Thanks.
From an object of the C class, you can access protected members of B, but only if they're part of some object of class C (maybe yours, maybe not). In other words, to access a from C, you need a pointer (or a reference) to C. This is what the protected modifier means.
The reason for this is the following. The ((B*)parent) pointer may point to some other subclass of B, completely different from C, and that subclass may have the a member inaccessible.

Instance of a subclass in a parent class

I have two classes in a class hierarchy where a parent class needs to have an instance of a class derived from it as a member variable. As an example:
class B;
class A {
public:
B* binst;
A();
};
class B : public A {
};
A::A() {
binst = new B;
}
Obviously, this causes an infinite recursion in the constructors, because to create a new B you have to call A's constructor, which creates a new B which calls A's constructor, and so ad infinitum.
Is there a way around this? The problem I'm having in this is that A has to have a B in it, but B must be derived from A, and there's not a way to prevent that.
To get an idea of why I need to do this, consider an object oriented hierarchy for a scripting language (like python or ruby or lua, etc):
All instances of anything are derived from a base class, Object.
Object has a method lookup table, which is an instance of MethodTable.
MethodTable is derived from Object, and must be, for the scripting language to be able to operate on it.
"Object has a method lookup table"
"MethodTable is derived from Object"
Putting aside coding concerns, do these statements really make sense together from even a conceptual standpoint? Should a MethodTable have its own MethodTable which then has its own MethodTable... etc?
I'd say it sounds like you need to refactor your concepts a bit. For instance, perhaps Object itself should somehow be responsible for exposing the necessary pieces of its MethodTable member. Thus not requiring MethodTable itself to be an Object. (There may be various other feasible designs too. It's hard to say without deeper knowledge of the actual project.)
Edit: Typically, compiler/implementation-internal types don't derive from language-dependent types. If you look at the internals of Java, their inheritance implementation won't derive from Object. Object is a language construction, it's part of your language's interface. A method table is part of the implementation. A method table should not be operated on by the language, it should be operated on by the implementation.
Moreover, enforced deriving from Object is a stupid thing to do and it happens because you didn't consider the language design and how the users were going to write generic code properly. This is especially true in dynamically typed languages like Lua or Python.
Object could have a private MethodTableImpl member and a public getter that returns a MethodTable. MethodTable contains a MethodTableImpl and derives from Object.
I don't know the purpose of your classes but here is a suggestion :
class A
{
public:
virtual void func DoIt () = 0;
...
};
class B : public virtual A
{
public:
};
class C : public virtual A ,B
{
void func DoIt () { /* statements */ }
};
now there is only 1 instance of class A.
It would be helpful to understand exactly are you trying to achieve via this construct.
As you've noted yourself, this is effectively like having A's constructor construct an instance of A, and that's an unavoidable path to stack overflow.
A more general solution would be to provide a set_subclass method for a pointer to an instance of A, which could then be populated by any subclass of A, not just B.
class A {
public:
A();
virtual ~A();
set_subclass(A* sub) { subclass = sub; }
private:
A* subclass;
};
// List(1) or Stream(2) using inheritance
struct B;
struct A {
B *inst;
A(B *inst_) : inst(inst_) {}
A() : inst(0) {}
};
struct B : A {
B(B *_inst) : A(inst) {}
// chose option 1 or 2
B() : A() {} // option 1: List
B() : A(0) {} // same as above
B() : A(this) {} // option 2: Stream
};
auto B3 = new B(new B( new B));
// This is either a length 3 list (1)
// or a stream (2) implemented by self ref 3rd element
You can make a constructor for class A which accepts a pointer to an object to class B and assign this pointer instead of allocating a new B:
A::A(B* b) : binst (b) {}
And in the construct of class B you pass 'this' in constructor of A:
B::B() : A(this) {}
The compiler will probably complain about it, but you can try. (It is ugly, though.)
Note that you can NOT use the binst pointer to access object B in A's constructor, because it's not fully constructed yet.
Does it actually need the binst as a member, or does it simply need to access it?
class B;
class A {
public:
B& binst(); //throws exception if not derived from B
A() {}
virtual ~A() {} //effectively required for the dynamic_cast
void foo();
};
class B : public A {
public:
void bar() {};
};
B& A::binst() {return dynamic_cast<B&>(this);}
void A::foo() {return binst().bar();}