I have a simple question. How would you go about passing an instance of a class to a constructor of another class in c++? I have experience in C, however I am struggling with the syntax of c++.
For example say I have Class A and want to pass and Instance of it to Class B.
A.h
class A {
A();
virtual ~A();
public:
B *newb;
}
A.cpp
A::A() {
newb = new B(this);
}
b.h
class B {
B(A *instanceA);
virtual ~B();
}
Could someone please provide me with a simple example? It would be much appreciated.
EDIT: I tried this concept with my current code, but kept getting errors. Sorry I wanted to make sure that I used the right principle. This is a snippet of the code that I am currently working on.
//SentencSelection.h
class SentenceSelection
{
public:
SentenceSelection(TestBenchGui *test);
virtual ~SentenceSelection();
//do stuff
};
//SentencSelection.cpp
#include <iostream>
#include "SentenceSelection.h"
using namespace std;
SentenceSelection::SentenceSelection(TestBenchGui *test)
{
//do stuff
}
SentenceSelection::~SentenceSelection()
{
}
//TestBenchGui.h
#include "SentenceSelection.h"
class TestBenchGui
{
public:
TestBenchGui();
virtual ~TestBenchGui();
private:
SentenceSelection *selection;
};
//TestBenchGui.cpp
#include "TestBenchGui.h"
#include "SentenceSelection.h"
using namespace std;
TestBenchGui::TestBenchGui()
{
selection = new SentenceSelection(this);
}
TestBenchGui::~TestBenchGui()
{
}
When I compile this in eclipse I get the follwing error "expected constructor, destructor, or type conversion before ‘(’ token" for the line - "SentenceSelection::SentenceSelection(TestBenchGui test)" in SentenceSelection.h.
I believe the code you have does pretty much what you are asking, but there are a couple of syntax errors that are probably holding you back from compilation (and thus leading to some confusion). Below is code that I put in a single file (main.cpp) and was able to compile. I added some comments and print statements to highlight the difference between DECLARATIONS and IMPLEMENTATIONS:
#include <iostream>
using std::cout;
using std::endl;
// forward declaration so we can refer to it in A
class B;
// define A's interface
class A {
public:
// member variables
B *newb;
// constructor declaration
A();
// destructor declaration
virtual ~A();
}; // note the semicolon that ends the definition of A as a class
class B {
public:
// B constructor implementation
B(A *instanceA){cout << "I am creating a B with a pointer to an A at " << instanceA << endl;}
// B destructor implementation
virtual ~B(){cout << "Destructor of B" << endl;}
}; // note the semicolon that ends the definition of B as a class
// A constructor implementation
A::A(){
cout << "I am creating an A at " << this << ", allocating a B on the heap..." << endl;
newb = new B(this);
}
// A destructor implementation
A::~A(){
cout << "Destructor of A, deleting my B...." << endl;
delete newb;
}
int main(){
A an_a;
}
Output for my system from running the above program:
I am creating an A at 0x7fff64884ba0, allocating a B on the heap...
I am creating a B with a pointer to an A at 0x7fff64884ba0
Destructor of A, deleting my B....
Destructor of B
Hope this helps.
For example say I have Class A and want to pass and Instance of it to Class B.
If you intend to pass a pointer to the instance, then you have already figured it out. The constructor that you declared takes an A* as an argument:
B(A *instanceA);
#include <iostream>
using namespace std;
class B
{
public:
B(){};
int x;
~B(){};
};
class A
{
public:
A(){}; // default constructor
A(B& b) // constructor taking B
{
y = b.x;
}
~A(){};
int y;
};
int main()
{
B myB;
myB.x = 69;
A myA(myB);
cout << myA.y << endl;
return 0;
}
I answer strictly your question:
If you want to pass a instance on a constructor best practice is pass as a reference:
class CA{
CB &b;
public:
CA( CB &p_b) : b(p_b){};
virtual ~CA();
};
But in your example you have a classes with cross references that is another case
Related
Sorry if this has been asked before; I found similarly titled questions, but none of them focused on the same aspects I'm having trouble with.
There's a class A, and a class B that should only be accessible from A. I think nesting B inside A will achieve that, but I'm struggling with the logistics.
A has a B as a member. As such, not defining B prior to declaring A's members causes incomplete type errors. I thought I'd get around this by declaring A, defining A::B, then defining A, but that just throws the same errors plus incomplete type 'A' in nested name specifier.
class A;
class A::B
{
...
};
class A
{
private:
class B;
B b;
...
};
The only functional examples I can find would put B's member declaration directly inside A's, which I'd really like to avoid doing: B's header information is several times longer and much denser than A's. Splitting the two up into separate files would be best, but actually nesting them inline is incredibly unwieldy.
Fallback options at this point include making A's B a pointer (no real reason why not, but is this really something that can't be done?) and leaving them as independent classes. But surely this can't be that hard?
What do I need to declare to link these properly and in what order?
I am not particularly knowledgeable about the depths of C++ so please explain like I'm five and refrain from shaming me into the ground for not knowing everything.
Since b is a non-reference non static data member of class A, it must be declared to have a complete type.
One way to solve this would be to either make b a reference type(as shown below) or a pointer to a B:
class A
{
private:
class B;
//--vv------------>now b is an lvalue reference to a B object
B& b;
};
class A::B
{
};
Method 2
Other option is to define B inside A with only its member declaration and then define those members outside as shown below:
class A
{
private:
//defined class now
class B
{
void member1();
};
B b; //works now
};
void A::B::member1()
{
}
One particularly non-convoluted way of doing this would be
class B
{
friend class A;
private:
// everything;
};
class A
{
B b;
};
This of course makes all the guts of B accessible to A, bit if B is such A-specific, it should not be a problem.
If this is not desirable, a slightly wore windy path to a solution would be
class PreA
{
protected:
class B { ... };
};
class A : PreA
{
B b;
};
The only functional examples I can find would put B's member
declaration directly inside A's, which I'd really like to avoid doing:
B's header information is several times longer and much denser than
A's. Splitting the two up into separate files would be best, but
actually nesting them inline is incredibly unwieldy.
The premise is interesting until I saw this comment of yours, I assume by you mean "Hide" is "Hide the Code it Self", not the members and method of B?
B is already tailored to the specifics of A and wouldn't be reusable
without modification. That's really why I want to hide it.
And with this line, can I assume that you aren't familiar with the concept of inheritance?
I am not particularly knowledgeable about the depths of C++ so please
explain like I'm five and refrain from shaming me into the ground for
not knowing everything.
You can simply inherit Class A into Class B, then use Class B itself? or the other way around. Just remember that the Base Class [Class A in this Case] has no idea what methods or member the Derived Class has [Class B in this Case].
e.g.All (Derived)Airplanes can (Base)Fly but not everything that can Fly is an airplane.
A Little Introduction to Inheritance can be found here. and if you do decide to go through this route, please Read up on a lot of materials about it. It's a Deep hole.
class A
{
public:
A()
{
x=0;
y=0;
std::cout << "A's Default Constructor Used " << std::endl;
}
virtual ~A(){std::cout<<"A's Destructor called" << std::endl;};
int x;
int y;
};
class B : public A
{
public:
B(){}
B(int nX, int nY){x=nX,y=nY;}
~B(){std::cout<<"B's Destructor Called"<<std::endl;}
public:
void SomeMethod(int nX){x+=nX;}
};
int main() {
B b;
std::cout << b.x << " " << b.y << std::endl;
b.SomeMethod(10);
std::cout << b.x << " " << b.y << std::endl;
}
NOTE: On A's destructor [virtual ~A(){std::cout<<"A's Destructor called" << std::endl;};] the keyword virtual is not needed unless you are deleting / destroying Class B from a Pointer to an Object of Class A, and Absolutely necessary if you are, Like Below.
B* b = new B;
std::cout << b->x << " " << b->y << std::endl;
b->SomeMethod(10);
std::cout << b->x << " " << b->y << std::endl;
A* a = b;
delete a;
Without the virtual keyword, only A's Destructor would be called and not B's.
Unless inheritance is out of the question then Nesting(Which I personally don't recommend it's a big pain on maintenance) ,creating a pointer of Class B inside A.
Or simply create Class B inside Class A like below.
class B
{
public:
B()
{
z = 0;
std::cout<<"B Default Constructor Used"<<std::endl;
}
B(int nZ)
{
z = nZ;
std::cout<<"B Constructed"<<std::endl;
}
~B(){}
public:
void SomeMethod(int& nX,int nY){nX += ( nY + z );}
int z;
};
class A
{
public:
A()
{
x=0;
y=0;
std::cout << "A Default constructor used" << std::endl;
}
A(int nX,int nY,int nZ)
{
x = nX;
y = nY;
b.z = nZ;
std::cout << "A's Constructed" << std::endl;
}
~A(){};
B b;
int x;
int y;
};
int main() {
A a;
a.b.SomeMethod(a.x,10);
std::cout << a.x << std::endl << std::endl;
// Ore something like this;
A a2 = A(1,2,3);
a2.b.SomeMethod(a2.x,20);
std::cout << a2.x << std::endl;
}
Just remember to create a Default Constructor for Class B since it would be called during the creation of Class B. Take note that I am speaking from my personal Experience and Knowledge, and by no means is it gospel, specially when I am self taught, and Using conventions that I am using in my own projects.
Declaring a Class static is one way to prevent Class B's Creation as Well but able to use it's functions . But I rarely find the need to do this in productions. I've mainly used this in debugging things. Since I've only seen it used in C#, and I've never tried it using it in production since I don't know what kind of behavior it could produce.
#include <iostream>
static struct B
{
protected:
B(){};
public:
static void PrintSomething(int x)
{
std::cout <<"Printing Something " << x <<std::endl;
}
static void MultiplyBy2(int* x)
{
int Two = 2;
*x = *x * Two;
}
};
class A
{
public:
A(int nX,int nY):X(nX),Y(nY){}
public:
int GetX()const{return X;}
int GetY()const{return Y;}
int* PointerToX() {return &X;}
private:
int X;
int Y;
};
int main()
{
A a(1,2);
B::PrintSomething(a.GetX());
B::MultiplyBy2(a.PointerToX());
B::PrintSomething(a.GetX());
B::MultiplyBy2(a.PointerToX());
B::PrintSomething(a.GetX());
return 0;
}
The goal of the code structure below is to be able to store pointers to objects of any class inherited from 'A'.
When I run this code, I get 0 written out, but what I'm trying to access is the 'B' object's 'num' value, which is 1. How can I do that?
As far as I know, when you create an inherited class's object, you create an object of the parent class too automatically. So can I somehow access the parent class object from it's child and set it's class member to match?
See minimal reproducible example below.
Update: Virtual functions solved the problem.
#include <iostream>
class A
{
public:
int num;
A()
{
num = 0;
}
};
class B : public A
{
public:
int num;
B()
{
num = 1;
}
};
class C
{
public:
A* ptr_array[2];
C()
{
ptr_array[0] = new B();
}
void print()
{
std::cout << ptr_array[0]->num << std::endl;
}
};
int main()
{
C* object_c = new C();
object_c->print();
return 0;
}
The problem is that you define a member num in A, and another member num in B. So an object of type B has two members called num, and you're leaving it to the compiler to choose which one to use -- which it does, according to logical rules which may be unfamiliar to you.
If you remove the line in num; from the definition of B, the code will work as you intend.
Your array is a red herring. You are only using one pointer. Might just as well have it as a member for the sake of the example.
I suppose you might need something like this (note, untested code).
#include <memory>
#include <iostream>
class A {
public:
A() : m_num(0) {} // use this instead of assignment in the c'tor body
virtual int getNum() { return m_num; } // this is **the** way to use inheritance
virtual ~A() = default; // required
private:
int m_num;
};
class B : public A {
public:
B() : m_otherNum(1) {}
virtual int getNum() { return m_otherNum; } // does something different from A
private:
int m_otherNum; // you could also call it m_num, but for clarity I use a different name
};
class C {
public:
C() : m_a (std::make_unique<B>()) {} // note, use this instead of new B
void print() {
std::cout << m_a->getNum() << std::endl;
}
private:
std::unique_ptr<A> m_a; // note, use this instead of A* m_a;
};
I have no way of knowing if this is really what you need (or you think you need). This is how inheritance is supposed to be used in object-oriented programming. You can use it in various other ways and produce correct (as far as the language definition is concerned) programs. But if this is the case, then (public) inheritance is likely not the best tool for the job.
I am trying to write a simple program in c++ where I have 2 classes, and both can access functions from each other. This is a simplification of what I am actually trying to do in the end, which is to create a game with board and piece classes. I was able to do this in java, but I am now running into problems trying to do the same in c++. My code is as follows:
#include <iostream>
class B;
class A {
public:
void sync(B obj){
b = obj;
}
void print(){
std::cout << "Hello from class A" << std::endl;
}
void printBoth(){
std::cout << "Hello from class A" << std::endl;
b.print();
}
private:
B b;
};
class B {
public:
B(A obj){
a = obj;
}
void print(){
std::cout << "Hello from class B" << std::endl;
}
void printBoth(){
std::cout << "Hello from class B" << std::endl;
a.print();
}
private:
A a;
};
int main(){
A a;
B b(a);
a.sync(b);
a.printBoth();
std::cout << std::endl;
b.printBoth();
return 0;
}
When I try to compile this with g++ example.cpp, I receive 5 errors:
example.cpp:20:5: error: field ‘b’ has incomplete type
B b;
^
example.cpp: In member function ‘void A::sync(B)’:
example.cpp:7:8: error: ‘obj’ has incomplete type
void sync(B obj){
^
example.cpp:3:7: error: forward declaration of ‘class B’
class B;
^
example.cpp:8:4: error: ‘b’ was not declared in this scope
b = obj;
^
example.cpp: In member function ‘void A::printBoth()’:
example.cpp:17:4: error: ‘b’ was not declared in this scope
b.print();
^
I have never used forward declaration with classes, so I apologize if I am missing something glaringly obvious. Any help is appreciated, and I thank you in advance.
There are two problems with your code.
Let's take the first problem.
Here's an example of two classes with methods that call each other. Pretty meaningless, and results in an infinite loop, but this demonstrates the general principles of forward declarations, and you can use this as a template to fix the code you've shown.
class A {
public:
void foo();
};
class B {
public:
void foo();
};
void A::foo()
{
B b;
b.foo();
}
void B::foo()
{
A a;
a.foo();
};
Now, the second problem with your code:
As written, your class A contains an instance of class B, which contains an instance of class A, which contains an instance of class A, which contains an instance of class B, all the way until the universe implodes in one massive black hole. Suffice to say, this is not going to compile.
C++ objects are fundamentally different from Java objects. They work in completely different ways. You can do this in Java because the dirty little secret is that all objects in Java are really a mirage, they are really reference-counted pointers to the actual objects. In C++, the closest equivalent of this would be to declare a std::shared_ptr to the object:
#include <memory>
class A;
class B;
class A {
// ...
private:
std::shared_ptr<B> b;
};
class B {
// ...
private:
std:shared_ptr<A> a;
};
And this would be the second problem with your shown code. In general, you need to pretty much forget everything you know about Java objects, when learning C++ objects. They are fundamentally different, and trying to consistently draw analogies between what you already know about Java objects, and C++ objects, will only lead to confusion.
You can always try to redesign i.e:
#include <iostream>
#include "A.hpp"
int main(){
A a;
B b(a);
a.sync(b);
a.printBoth();
std::cout << std::endl;
b.printBoth();
return 0;
}
B.hpp:
class A;
class B {
public:
B() {}
B(A obj);
void print();
void printBoth();
private:
A* a;
};
B.cpp:
#include <iostream>
#include "A.hpp"
B::B(A obj){
a = new A(obj);
}
void B::print(){
std::cout << "Hello from class B" << std::endl;
}
void B::printBoth(){
std::cout << "Hello from class B" << std::endl;
a->print();
}
A.hpp:
#include "B.hpp"
class A {
public:
void sync(B obj);
void print();
void printBoth();
private:
B b;
};
A.cpp:
#include <iostream>
#include "A.hpp"
void A::sync(B obj){
b = obj;
}
void A::print(){
std::cout << "Hello from class A" << std::endl;
}
void A::printBoth(){
std::cout << "Hello from class A" << std::endl;
b.print();
}
// In A.h
class A
{
public:
enum eMyEnum{ eOne, eTwo, eThree };
public:
A(eMyEnum e);
}
// In B.h
#include "A.h"
class B
{
B();
private:
A memberA;
}
// In B.cpp
#include "B.h"
B::B(void) : memberA(A::eOne)
{}
The declaration to 'memberA' gives me a compile error using the g++ compiler:
error: 'A::eOne' is not a type
How can I overcome this? Do I simply need to create a default constructor that takes no parameters?
It sounds like you are trying to initialise a member variable. You could do something like:
class B
{
public:
B() : memberA(A::eOne) {} // Initializer list in constructor
private:
A memberA;
};
A constructor expects a eMyEnum. It is not clear why you would want B's constructor to not accept an eMyEnum parameter too. Anyway, assuming that your aim is to pass the argument to A's constructor as A::eOne (as opposed to A::eMyEnum::eOne), you could try the following code, which uses typedef.
#include <iostream>
using namespace std;
class A {
public:
typedef enum { eOne, eTwo, eThree } eMyEnum;
public:
A(eMyEnum e) {
cout << "A ctor" << endl;
}
};
class B {
public:
B() : memberA(A::eOne) {
cout << "B ctor" << endl;
}
private:
A memberA;
};
int main() {
B b;
}
// output
A ctor
B ctor
However, notice that memberA's constructor is always called with the argument as A::eOne. You have not showed how this argument is used in the constructor, but I presume that in your real code it initialises a member of A. If the member must always have the same value, make it const and remove the parameter from the constructor.
class B
{
public:
B(A::eMyEnum someValue = A::eOne) : memberA(someValue) {};
private:
A memberA;
}
eOne is not the type, eMyEnum is the type. What you're essentially saying is that "You must pass the literal 2 into this method" - it doesn't make any sense. If you don't mean to pass an enum into it, you'll have to clarify what you were going for.
The following code gives an compilation error for void b() { m = &A::a; }; stating that A::a() is protected. (Which it is - but that should be no problem)
However the compiler doesn't care when I write B::a(). Even though both mean the same I would prefer A::a() because it states explicitely that a() is defined in A.
So what is the reason why A::a() is forbidden?
EDIT
Maybe someone can find an example that would be problematic if A::a() was allowed in B::b(). If there is such an example, I will mark it as answer to the question.
/EDIT
#include <iostream>
#include <iomanip>
#include <string>
#include <cstdio>
class A {
protected:
void a(){ std::cout << "A::a()" << std::endl; };
};
typedef void (A::*f)();
class B : public A {
public:
void b() { m = &A::a; }; // wont compile
// void b() { m = &B::a; }; // works fine
void c() { (this->*m)(); };
protected:
f m;
};
int main(){
B b;
b.b();
b.c();
}
// compile with
// g++ -Wall main.cpp -o main
Explanation of the code:
In B I want to store a function pointer to a method in A to be able to call that later in B::c(). And yes, this happens in real life too. :-)
Because otherwise the outside world can find this protected member: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11174.
See also http://gcc.gnu.org/ml/gcc-patches/2004-06/msg00610.html.
The reason should be similar to why you can't do this in B either:
class B: public A
{
//...
void foo(A& x) {
x.a(); //error
}
void foo(B& x) {
x.a(); //OK
}
};
That protected doesn't mean that B can access the A part of any class as long it is an A / derived from A. The protected stuff is only available for this and other instances of B.
You try to access protected member through global namespace (A::a is ::A::a here), use B::A::a instead.