C++ pointers to class instances - c++

I have an (for C++ programmers better than me) simple problem with classes and pointers.
I thought about posting example code describing my problem but I found it easier to just explain it in words.
Assuming I have three classes:
Class A: The main class - it contains an instance of both B and C.
Class B: This class contains a method that outputs some string, call it Greet().
Class C: This one has a method too, but that method has to call Greet() in the instance of B that is located in class A. Let's name it DoSomethingWithB()
So the program starts, in the main function I create an instance of A. A, again, creates instances of B and C. Then, A calls C.DoSomethingWithB();.
And there my problem begins: I can't access B from inside C.
Obviously, I will need to pass a pointer to B to the DoSomethingWithB() function so that I can call B.Greet() from inside C
Long explanation, short question: How do I do this?
Example code incoming:
#include <iostream>
using namespace std;
class B
{
public:
void Greet( )
{
cout<<"Hello Pointer!"<<endl;
}
};
class C
{
public:
void DoSomethingWithB( )
{
// ... b.Greet( ); Won't work obviously
}
};
class A
{
public:
B b; // Not caring about visibility or bad class/variable names here
C c;
void StartTest( )
{
c.DoSomethingWithB( );
}
};
int main( )
{
A mainInstance;
mainInstance.StartTest();
}

Wouldn't you simply pass a pointer or reference to he B object?
class C
{
public:
void DoSomethingWithB( B& b)
{
b.Greet( ); // will work fine
}
};
class A
{
public:
B b; // Not caring about visibility or bad class/variable names here
C c;
void StartTest( )
{
c.DoSomethingWithB( b);
}
};
If the DoSomethingWithB() function won't modify the passed in B instance, you should mark the reference const so it can be called with a const B object (for example if the owning A object happens to be const):
void DoSomethingWithB( B const& b);
You have a few options for how to pass the B object to the function:
as a reference (void DoSomethingWithB( B& b)) which will let the function modify the passed in object. Changes will be refelected in the object that's passed in.
as a const reference (void DoSomethingWithB( B const& b)) which won't let the function modify the passed in object (unless the constness is cast away - something which can lead to undefined behavior if done on an object the is truely const)
as a pointer or const pointer to a B object (void DoSomethingWithB( B* b) or void DoSomethingWithB( B const* pb) ). These have similar performance to passing by reference, but the function could be passed a NULL pointer which needs to be dealt with properly (by not dereferencing it in that case). Also, the call of the function would need to change slightly to pass the address of the B object:
c.DoSomethingWithB( &b);
as a pass-by-value parameter (void DoSomethingWithB( B b)). This has difference that the function can do whatever it likes with theo bject passed in and it won't affect the originally passed object since the function is dealing with a copy. The disadvantage is that passing the parameter causes a copy to be made which might be expensive. You could also pass in a const value, but there's little to recommend that over passing a const reference.
Note that when chosing the parameter passing method, you should first chose based on the sematics of what you need the function to do (or not do). Worry about efficiency later. Always first design and code for correctness - worry about efficiency only after you have the design and code correct.

Change the functions to the following:
void DoSomethingWithB(B& b)
{
b.Greet();
}
... and in A ...
c.DoSomethingWithB(b);

You can do it just as you said -- pass a pointer (or a reference) to B in to DoSomethingWithB():
class C
{
public:
void DoSomethingWithB(B & bInstance)
{
bInstance.Greet( ); // should work fine!
}
};
Then you'll invoke it like so:
class A
{
public:
B b; // Not caring about visibility or bad class/variable names here
C c;
void StartTest( )
{
c.DoSomethingWithB( b );
}
};
I'd suggest using the reference approach here rather than a pointer, since:
Your object is an automatic class member, and
Passing a null B object into the function is not meaningful in this case.

In class C, declare the method DoSomethingWithB() like this:
void DoSomethingWithB( B* b )
{
b->Greet();
}
And in class A call it like this:
void StartTest()
{
c.DoSomethingWithB( &b );
}
Since you mentioned pointers, I answered using pointers. In C++ however, you should try to use const references whenever you can. That would of course require a small change to the existing code:
void DoSomethingWithB( const B& b )
{
b.Greet();
}
// and
void StartTest()
{
c.DoSomethingWithB( b );
}

I can't access B from inside C
Instead of having C call methods in B, why not have C return information to the caller so it can do the operation?
When I hit these I've found it's because I've got my classes organized poorly. Usually if I rethink them the difficulty disappears with a new organization.

class C
{
public:
C (B & b) : b(b) {}
void DoSomethingWithB( )
{
// ... b.Greet( ); Use b;
}
private:
B & b;
};
class A
{
public:
B b; // Declare b before c!
C c;
A() : c (b) {}
void StartTest( )
{
c.DoSomethingWithB( );
}
};

Related

Using Child on a function with Parent's Typing

I was looking to create a function that is capable of working with any Derived Object of A.
However in this example, I can't seem to be able to use B Object in a function that has a A Typing on it. Is there any way I pass B into the Function?
class A {
public:
A() {
}
};
class B :A {
public:
B() {
}
};
void function(A a) {
return;
}
int main(void) {
B b();
function(b);
}
I've commented on the fixes needed inline:
class A {
public:
A() {}
};
class B : public A { // public inheritance or A will be an inaccessible base of B
public:
B() {}
};
void function(const A& a) { // take a reference to an A to avoid copy-slicing
// ... work with the A part of the object you reference with `a`
}
int main() { // void not needed (but not an error as such)
B b; // not a function declaration anymore
function(b);
}
Actually you are lucky. You made two mistakes that caused passing b to the function fail, while in fact without that other mistakes you can pass b to the function but it would do the wrong thing silently.
First the two mistakes: B b(); declares a function. To declare a default constructed B you write B b;. Then B inherits privately, hence you cannot convert a B to an A. Thats what the error your code causes have told you.
However, after fixing those (and removing user declared constructors taht shouldnt be there when they do nothing)...
class A {};
class B : public A {};
void function(A a) {}
int main(void) {
B b;
function(b); // object slicing !!
}
This code compiles without errors, but usually it does the wrong thing!
Any B can be converted to an A because the inheritance is public, but what happens is object slicing: What is object slicing?. If B had any members not in A then they would all be lost when passing it to function. Its not an issue here because neither A nor B have any members, but in general you want to avoid objects to get sliced.
TL;DR: References / pointers are needed for polymorphism. Pass by (const) reference:
void function(const A& a) {} // does not modify a
void function(A& a) {} // modifies a

Avoid null pointers while accessing objects in a tree hierarchy of classes

I have to work with a tree based hierarchy of objects where I need to access the deepest element that contains the data required by the application. I'm not sure if the previous statement explains in its best the problem itself so its better to present it with an example. Given the following scenario:
class A {
private:
B* _b;
public:
B* getB() {return _b;}
};
class B {
private:
C* _c;
public:
C* getC() {return _c;}
};
class C {
private:
int _n;
public:
int getN() {return _n;}
};
The desired operation would be to access n via A. So I would call the following:
A foo;
foo.getB()->getC()->getN();
The problem comes when any of the parts of the path are null we end up having a core dump. In the above scenario if B is null we end up in a core dump scenario.
Therefore I seek help and advice on any strategy or pattern that I can use to avoid this core dumps scenarios. If the path is extremely big I end up checking every single pointer if its valid and end up having really ugly code and also risk that I might have missed checking a part of the path. Note: I do not have access to change the implementation of the hierarchy of classes (A,B,C) as they are generated code and I do not have access to change the generator. Changing the previous would be my preferred solution but unfortunately I cannot.
In order to avoid having null pointers, you may want to establish a class-invariant that the member is never null. This can be achieved with following steps:
Encapsulate access to the member so that nothing outside the class can set the member. You've already achieved this through the use of private access. Just make sure that you pass/return a reference or a pointer to the member from a member function to the outside.
Ensure that no member nor friend function ever sets the member to null.
Also ensure that the member is always initialised. This is achieved by use of a custom constructor. Example:
class A {
B* b;
public:
A(B* b) : b(b) {
if (!b) {
// unlike indirection through null pointer, an exception can
// be caught and (potentially) handled gracefully at runtime
throw std::runtime_error("Naughty!");
}
}
// following prevents passing null literal at compile time
A(std::nullptr_t) = delete; // nullptr
A(int) = delete; // 0
// since it is never null, we can safely return a reference
B& getB() {return *b;}
}
While references have the nice property of not being ever null, they are tricky as members, since they are also not assignable. As an argument to a constructor, they are tricky since it is generally not conventional or expected for a class object to keep references to objects passed into a constructor. As such, I advocate the use of pointers in this case even when null is undesirable.
Note: I do not have access to change the implementation of the hierarchy of classes (A,B,C) as they are generated code and I do not have access to change the generator.
In this case you may instead wrap the generated classes with better classes:
class AWrapper {
A a;
// custom implementation that encapsulates A
}
If null pointers are valid values that cannot be avoided, then such invariant is of course not possible. In such case, you must always check whether the pointer is null before indirecting through it:
if (B* b = foo.getB())
if (C* c = b->getC())
c->getN();
Another thing that you might consider is whether all these pointers are necessary. Perhaps it would be simpler if the classes contained each other instead of indirectly referring to one another.
You need to test all along the way:
A foo;
B* BPrt = foo.getB();
if (BPrt)
{
C* CPtr = BPrt->getC();
if (CPtr)
{
int n = CPtr->getN();
...
Here's how I solved the problem:
#include <iostream>
using namespace std;
class C {
private:
int _n;
public:
int getN() {return _n;}
};
class B {
private:
C* _c;
public:
C* getC() {return _c;}
};
class A {
private:
B* _b;
public:
B* getB() {return _b;}
};
int main(void);
int main() {
static B b;
static C c;
static A foo;
unsigned int n;
B *bPtr; C *cPtr;
/* --RECODE (CHAIN-CALL): foo.getB()->getC()->getN();-- */
bPtr = (B *) (foo.getB());
cPtr = (C *) (bPtr ? bPtr->getC() : 0);
n = (int) (cPtr ? cPtr->getN() : 0);
/* --USE (CAST) and (TERNARY) instead of (CHAIN-CALL)-- */
cout << n << endl;
return n;
}
If the classes cannot be changed then the checking could be done via a template:
template <typename T, typename A, typename ...Args>
auto recurse(T t, A a, Args... args)
{
if (!t)
throw std::exception{};
auto next = (t->*a)();
if constexpr (sizeof...(Args) > 0)
return recurse(next, args...);
else
return next;
}
Then call as follows:
recurse(&foo, &A::getB, &B::getC, &C::getN);
The problem is not with a pointer being null. That is in-fact good as it mostly crashes at runtime. What if it's not null but has been previously freed/deleted ? The usage will probably lead to Undefined Behaviour.
A better way would be to use references if you can:
class A
{
private:
B& _b;
public:
A(B& b): _b{b} {}
B& getB ()
{
return _b;
}
};
Or something like that. Then you at-least don't have anything dangling (unless you are also using pointers somewhere).
If you have to use pointers then use one of the smart-pointers - see if std::unique_ptr solves if for you. If not then for shared ownership use std::shared_ptr and so on. Also ensure the way you initialise objects don't lead to a default null there.
You can make sure that your pointers are always initialized, if possible:
class C {
private:
int _n = 0;
public:
int getN() {return _n;}
};
class B {
private:
static C default_c;
C* _c = &default_c;
public:
C& getC() {return *_c;}
};
C B::default_c; // An out-of-line static member definition is required.
class A {
private:
static B default_b;
B* _b = &default_b;
public:
B& getB() {return *_b;}
};
B A::default_b; // An out-of-line static member definition is required.
int main() {
A a;
std::cout << a.getB().getC().getN() << '\n';
}
Note that pointers make better members than references because the references break value semantics and make your class non-assignable.
Did you consider:
try {
foo.getB()->getC()->getN();
}
catch(...)
{
//Here you know something is Null
}
That seems the simplest safest,when dealing with existing code.

How to distinguish objects of derived classes C++

Look at following code:
class A
{
protected:
int aa = 1;
};
class B : public A
{
private:
int bb = 2;
public:
int getbb() { return bb; }
};
class C : public A
{
private:
int cc = 3;
public:
int getcc() { return cc; }
};
int main()
{
std::vector<A> a;
B b;
C c;
a.push_back(b);
a.push_back(c);
a[0].getbb(); //getbb() unaccessible;
a[1].getcc(); //getcc() unaccessible;
}
A is the based class. B and C is the derived classes. I want to set a vector to hold either B or C, and use vector a to hold A. However, since a is a vector containing A's objects, I can't access methods in B and C. Is there anyway to make a[0].getbb() and a[1].getcc() work?
Your vector of A is not capable of holding Bs or Cs, because it stores A by value, resulting in object slicing when B or C is stored. In particular, this means that when you store B, only aa gets stored; bb gets sliced away.
In order to store subclasses without slicing use a container of pointers - preferably, of smart pointers.
This wouldn't help you access functionality specific to B or C without a cast. One way to solve this problem is to give virtual member functions for B's and C's functionality to A, and make calls through A-typed reference of B or C.
Not without invoking undefined behaviour.
The problem is that a.push_back(b) and a.push_back(c) do not append objects b and c to the vector. They create instances of A that hold only the "A parts". This is called object slicing.
So there is no object of type B and no object of type C in the vector.
You force the issue and make your code compile by doing something like
static_cast<B &>(a[0]).getbb();
but this just has undefined behaviour, since it treats a[0] as being of type B when it is really of type A. Which makes it a really bad idea. Although it will (probably) compile, it could do anything - and probably not what you expect.
If your vector contains A * rather than A it is possible. For example;
int main()
{
std::vector<A *> a;
a.push_back(new B);
a.push_back(new C);
B* b = dynamic_cast<B *>(a[0]);
if (b) // if a[0] actually points at a B ....
b->getbb();
else
complain_bitterly();
C *c = dynamic_cast<C *>(a[1]);
if (c)
c->getcc();
else
complain_bitterly();
}
Of course, doing this has practical trap doors as well - such as requiring class A having at least one virtual member. It would be better off to work with a polymorphic base, and override virtual functions.
In other words, your design is broken, so fix it so it doesn't somehow require you to morph an object to a different type.
An alternative to using pointers is to use a vector of std::reference_wrappers and polymorphic classes. Small example below:
#include <functional> // for std::reference_wrapper
#include <iostream>
#include <vector>
class A
{
public:
virtual void printme()
{
std::cout << "A" << std::endl;
}
virtual ~A() = default;
};
class B: public A
{
public:
void printme() override
{
std::cout << "B" << std::endl;
}
};
class C: public A
{
public:
void printme() override
{
std::cout << "C" << std::endl;
}
};
int main()
{
std::vector<std::reference_wrapper<A>> a;
B b;
C c;
a.emplace_back(b);
a.emplace_back(c);
a[0].get().printme(); // need to "get()" the raw reference
a[1].get().printme();
}
Live on Coliru
According the the cpp reference, there seems to be a way to achieve this by using dynamic_cast. You first need to make your vector a vector of pointers to the base class A. Then when accessing any element, you can check if it is a B* (or a C*) by checking the result of the dynamic_cast operator.
From the CPP reference:
dynamic_cast < new_type > ( expression )
... If the cast is successful, dynamic_cast returns a value of type new_type. If the cast fails and new_type is a pointer type, it returns a null pointer of that type...
Accordingly, you can do this:
std::vector<A*> a;
B b;
C c;
a.push_back(&b);
a.push_back(&c);
...
int i = something;
B* pB = dynamic_cast<B*>(a[i]); if(pB != nullptr) pb->getbb();
C* pC = dynamic_cast<C*>(a[i]); if(pC != nullptr) pC->getcc();
p.s: It is highly questionable as design approach though. The recommended OOP approach would be certainly to use a virtual method in the base class A and override it in B and C. But (hopefully) this answers the exact question as stated in the title.
If you're sure they're instances of B and C, use cast:
static_cast<B>(a[0]).getbb();
static_cast<C>(a[1]).getcc();
OK, you may also create a vector of A*:
std::vector<A*> as;
as.push_back(new B);
as.push_back(new C);
B* b = (B*) as[0];
b->getbb();
c->getcc();
Now you only have to remember about freeing objects with delete.
You may use "Type IDs":
class A {
// ...
virtual int getTypeID() { return 0; }
}
class B {
// ...
virtual int getTypeID() { return 1; }
}
// analogically for C
It's virtual but is in prototype of A
Now use:
switch(a.getTypeID()) {
case 0:
// It's normal A
break;
case 1:
// It's B
// ...
break;
case 2:
// It's C
// ...
break;
}

How to call a method in one object from another object in the same structure

I have the following situation:
class B
{
public:
void methodInB();
};
class C
{
public:
void methodInC();
};
class A
{
public:
void methodInA();
private:
B objB;
C objC;
};
void A::methodInA()
{
objB.methodInB();
}
int main()
{
A objA;
objA.methodInA();
return 0;
}
I want to be able to call C::methodInC() from within B::methodInB(), but I'm not sure what the way to go about it would be (not without messing with globals).
My first idea was to add a C* pC pointer as a member of B, and then from methodInB() call it as pC->methodInC. This would require I set the pointer from within A before using the method (possibly in A's constructor). My problem is I may need to call other objects from within B if I add a D and E objects, and I don't want to fill the class definition with pointers.
Is there some other way of doing this? An implicit reference to the object the object belongs to? Kind of like this but for the parent? So I could at least do parent->objC->methodInC()?
I think the cleanest way would be to "inject the dependency", that is, to pass objC to methodInB, which would then invoke methodInC on that object:
void A::methodInA()
{
objB.methodInB(objC);
}
// ...
void B::methodInB(C &objC)
{
objC.methodInC();
}
Let every class B, C, D, E, etc. have a pointer to the A object of which they are subobjects.
class A;
class C;
class B
{
A* pA;
void MethodB();
};
...
void B::MethodB
{
(pa->CObject).MethodC();
}

C++ OOP basics (assigning an object as a member)

I'm a PHP developer trying to write some C++.
I'm having trouble with assigning an object as an another object's property. In PHP, I'd write this:
class A {
public $b;
}
class B {
}
$a = new A;
$a->b = new B;
How do I do that in C++? I got this so far:
class A {
B b;
public:
void setB(&B);
};
class B {
};
void A::setB(B &b)
{
this->b = b;
};
A * a = new A();
B * b = new B();
a->setB(b);
What am I doing wrong?
Just do this:
class B
{
};
class A
{
B b;
};
int main()
{
A anA; // creates an A. With an internal member of type B called b.
// If you want a pointer (ie using new.
// Then put it in a smart pointer.
std::auto_ptr<A> aPtr = new A();
}
You don't actually need to create the B separately. The B b is part of the class and is created (using the default constructor) automatically when the A object is created. Creating the two objects seprately and then combining them is a bad idea.
If you want to pass some parameters to the B object as it is constructed. That is easy to do by creating a constructor for A that calls B's constructor:
class B
{
public:
B(std::string const& data) // The B type takes a string as it is constructed.
:myData(data) // Store the input data in a member variable.
{}
private:
std::string myData;
};
class A
{
public:
A(std::string const& bData) // parameter passed to A constructor
:b(bData); // Forward this parameter to `b` constructor (see above)
{}
private:
B b;
};
int main()
{
A a("Hi there"); // "Hi there" now stored in a.b.myData
}
Instead of &B, you mean B&.
class A {
B b;
public:
void setB(B&); //<--
};
A pointer cannot be implicitly dereferenced. So a->setB(b) won't compile. You need to write a->setB(*b).
You don't need new to construct an object. For example, this works:
A a;
B b;
a.setB(b);
Don't use idioms from other languages directly in C++. For example, setters and getters are seldom needed. In fact, your A class could just be a simple struct.
A couple changes will make it compile:
1. class B needs to be declared before A so that it can be used in class A
2. The declaration setB(&B) needs a minor change to setB(B&)
class B {
};
class A {
B b;
public:
void setB(B&);
};
void A::setB(B &b)
{
this->b = b;
};
int main ()
{
A * a = new A();
B * b = new B();
a->setB(*b);
}
To make it more efficient consider the adding the following constructor that accepts B as an argument and the initializes the member variable 'b'. This will use a copy constructor on the 'b' member variable instead of using the default constructor and then the assignment operator.
A(B& b_) : b(b_)
{
}
There are a lot of things wrong with this code:
As KennyTM notes, the ampersand is in the wrong place.
You are passing a B* to a function that takes a B&, they aren't the same in C++
The design shown in your php fragment appears to misdesigned. While what you are doing is something you might want to do at times, you'll usually want to use a constructor instead, C++ and PHP alike.
You are putting code directly in the file, this isn't allowed in C++, put it in the main function instead
memory management: you are using new without delete (or a smart pointer class)
You are using class B in class A while class A doesn't know about class B (it is defined later) - you should put class B on top (or perhaps use forward declaration)
A few ways to make your code work properly are shown below.
include <memory>
using std::auto_ptr;
class B
{
}
class A
{
public:
A();
SetB(B& b);
private:
B b1; // a B made in the constructor
B b2; // a COPY of the original B you make
}
A::A()
: b1(/*whatever you want to pass to B's constructor*/)
{
}
A::SetB(B& b)
{
b2 = b;
}
int main(int agrc, char** argv)
{
A firstA();
B firstB();
firstA.SetB(firstB);
A* secondA = new A();
B* secondB = new B();
secondA->SetB(*secondB);
auto_ptr<A> thirdA(new A());
auto_ptr<B> thirdB(new B());
thirdA->SetB(*thirdB);
// whatever other code
delete secondA;
delete secondB;
}
Note that id you call SetB only once (and there is no problem with cyclic depndencies between the different objects you are creating), but you do want the flexibility of constructing the B outside the class, you can instead make a parameter of the constructor.
Also note that you are making a copy of the B you create in main - if you want to use the came copy in the class (as you would in PHP), you should use a member reference (in which case you will need to set what it refers to in the constructor, you can't do so in the SetB function.
Then, note that there are serious problems with the secondA, secondB approach and as such it is not recommended (above nothing will go wrong, however, it is easy to get code that leaks memory this way (and hard to find out where the leak is) and on top of that when you want to use exceptions, you will need exception safe code, which is not achievable using plain old pointers.
Lastly, note that you mix and match here. There is no problem at all with using firstA and thirdB together, for example.