to create an instance of another class from a class even if the class I want to have an instance of is declared next of the class I am creating an instance from. Just like in C# and Java.
Thank you
You can use a forward declaration for some purposes, but you will need to have the complete type whenever you actually make use of it. It could be advisable to make the question more specific as to what you really want to achieve, as there might be simpler approaches to your problem (if order is important it might indicate a circular dependency between classes A and B, and that is not usually good).
class B;
class A
{
public:
A( B b, B* bp, B& br ) : bp_(bp), br_(br) {} // ok, incomplete types can be used as argument types
B f()
// { return B(); } // nok: cannot create objects of incomplete type
;
B* f2() { return bp_; } // ok
B& f3() { return br_; }; // ok
void g()
// { bp_->g(); br_.g(); } // nok: cannot call methods of an incomplete type
;
void g( B const & b )
// { b.g(); } // nok: cannot call methods of an incomplete type
private:
B * bp_; // ok (also const version)
B & br_; // ok (also const version)
// B b_; // nok: B must be a complete type here
};
class B { // A is complete, any use is correct here
void g() {}
};
// From here on, B is a complete type and can be used in any possible way
B A::f() {
return B(); // ok, now B is complete
}
void A::g() {
br_.g(); // ok, B is complete here
bp_->g(); // ok, B is complete here
}
void A::g( B const & b ) {
b.g();
}
Sure. You just need a forward declaration. Something like this works just fine:
#include <iostream>
class B;
class A {
public:
void hello( B &b );
void meow();
};
class B {
public:
void hello( A &a );
void woof();
};
void A::hello( B &b ) { b.woof(); }
void A::meow() { std::cout << "Meow!" << std::endl; }
void B::hello( A &a ) { a.meow(); }
void B::woof() { std::cout << "Woof!" << std::endl; }
int main() { A a; B b; a.hello( b ); b.hello( a ); return 0; }
The key here is that you can only use pointers or references to a class until it has been fully defined. So in the example I gave, the hello() method in A can be declared to take a reference to B, even though we haven't defined B at the point. After the definition of B, however, the definition of the method A::hello() is free to use B as it pleases.
I guess you mean to do something like this:
class B; //Forward declaration
class A
{
private:
B b;
};
class B
{
};
This is not possible in C++ as the compiler needs to know the sizeof(B) when compiling class A.
As a solution what you can do is:
class B; //Forward declaration
class A
{
public:
A();
~A();
private:
B* m_pB; //Store a pointer to B
};
class B
{
};
A::A()
{
m_pB = new B; //Create an instance of B
}
A::~A()
{
delete m_pB; //Explictly deallocate the memory.
m_pB = NULL;
}
Once you forward declare B in the header you can use it in the .cpp file without trouble to access public variables and methods.
Related
I have 2 classes lets say Class A and Class B,
class A {
public:
A(B b);
B GetB();
private:
B b;
};
class B {
public:
B();
void IncrementCounter();
int GetCounter();
private:
int counter = 0;
};
I want to pass an object of type B to class A's constructor and then save this instance of class B in Class A instance.
What is the best way to pass class B instance as a parameter, and what is the best way to save class B instance in class A instance.
Note: I do not want to create copies of class B instance, I want A.getB().GetCounter to always be the same as b.GetCounter().
int main(){
B b;
A a(b);
b.IncrementCounter();
a.getB().IncrementCounter();
// then b.GetCounter() is same as a.getB().GetCounter() and both = 2
}
I see people using pointers/smart pointer and references/std:reference_wrapper, what is the difference?
Use std::shared_ptr if you don't want copies, example :
I assume you are familiar with references, const references and const member functions.
#include <memory>
#include <iostream>
class B
{
public:
B()
{
number_of_instances++; // keep track of number of instances of class B
}
void IncrementCounter()
{
counter++;
}
int GetCounter() const
{
return counter;
}
int NumberOfInstances() const
{
return number_of_instances;
}
private:
int counter{ 0 };
static int number_of_instances;
};
class A
{
public:
A(const std::shared_ptr<B>& b) :
m_b{ b }
{
}
// return a reference to the object shared_ptr m_b points to
B& GetB()
{
return *m_b;
}
// return a const reference to the object shared_ptr m_b points to
const B& GetB() const
{
return *m_b;
}
private:
// https://en.cppreference.com/w/cpp/memory/shared_ptr
std::shared_ptr<B> m_b;
};
int B::number_of_instances{ 0 };
int main()
{
auto b = std::make_shared<B>();
b->IncrementCounter();
A a1(b);
A a2(b);
std::cout << "number of instances of B = " <<b->NumberOfInstances() << "\n";
std::cout << "shared_ptr<B> reference count = " << b.use_count() << "\n";
std::cout << a1.GetB().GetCounter();
return 0;
}
Note: I do not want to create copies of class B instance, I want A.getB().GetCounter() to always be the same as b.GetCounter().
Then you need to make A store a B& reference instead of a B object instance, eg:
class A {
public:
A(B& b);
B& GetB();
private:
B& b;
};
A::A(B& b) : b(b) {
}
B& A::GetB() {
return b;
}
As long as the B object outlives the A object (which it does in your example), you will be fine, no (shared) pointers will be needed.
However, since you are declaring A before B, you can't use B at all in A as you have shown. The compiler won't know what B is while parsing A.
Since B doesn't depend on A for anything, you can simply swap the order of their declarations, eg:
class B {
public:
B();
void IncrementCounter();
int GetCounter();
private:
int counter = 0;
};
class A {
public:
A(B& b);
B& GetB();
private:
B& b;
};
Otherwise, if that is not an option for your situation, then you will have to use a forward declaration of B before declaring A, eg:
class B; // <--
class A {
public:
A(B& b);
B& GetB();
private:
B& b;
};
class B {
public:
B();
void IncrementCounter();
int GetCounter();
private:
int counter = 0;
};
Forward declaration only work when dealing with references and pointers, not with instances.
In C++, can we return a pointer of A from a function whose actual return value is a different struct B which indeed has the first object as the pointer of A?
Consider the following scenario.
struct B {
A* ptr;
// code...
B(A* _ptr)
{
// code...
}
};
B foo()
{
A* tmp;
// code...
return tmp;
}
B bar()
{
A* tmp;
// code...
return B(tmp);
}
Will the foo() method work correctly? Will it be able to call the constructor?
Or foo() will not be able to call the constructor and it works only in the case when B was defined in the following way,
struct B {
A* ptr;
// code...
B(A* _ptr) : ptr(_ptr)
{
// some code (doesn't changes `ptr`)
}
};
OR in the following way
struct B {
A* ptr; // NO more data elements other than `ptr`
B (A* _ptr) : ptr(_ptr) {
// some code (doesn't changes `ptr`)
}
};
If it works, is it because A* ptr in B comes as the first object?
I'd like to know what are the possibilities for this on different C++ versions (<11, 11, 14, 17) or if it also depends on the compiler I use.
I suppose, bar is the best way to write it.
Let's test it!
#include <iostream>
struct A;
struct B {
B(A* _ptr)
{
std::cout << "I've been called!" << std::endl;
}
};
B foo()
{
A* tmp;
return tmp;
}
int main()
{
foo();
return 0;
}
The output of such simple program is:
I've been called!
Meaning that constructor has been called.
It's possible, because B (A* _ptr) is a conversion constructor. This type of constructor allows automatic conversion to the class being constructed.
Just as #john mentioned, to disable this behaviour we use explicit specifier.
explicit B(A*) and foo() is no longer accepted.
Additionally, as you can see, in my version of B, there is no member A* ptr; - it isn't required.
Further to what Jorengarenar said. Sometimes you want to disable this behaviour. This is what the explicit keyword does
#include <iostream>
struct A;
struct B {
explicit B(A* _ptr)
{
std::cout << "I've been called!" << std::endl;
}
};
B foo()
{
A* tmp;
return tmp;
}
int main()
{
foo();
return 0;
}
This version no longer compiles. return tmp; is an error but return B(tmp); would compile and call the constructor.
#include <iostream>
class A {
protected:
int foo;
};
class B : public A {
public:
B(int bar) { foo = bar; }
int method() { return foo; }
};
class C {
private:
A baz;
public:
C(A faz) { baz = faz; }
A get() { return baz; }
};
int main(void) {
C boo(B(1));
std::cout << boo.get().method() << std::endl;
return 0;
}
I have a base class A which B is a derived class of. Class C takes an A yet I have passed a derived class (B) in its place. No warnings or errors passing a B to C, but I'd like to have method visibility of method() in the above situation.
I'm not very familiar with virtual but I did try to add virtual int method() = 0; to A which lead to further errors.
Consider were I to add a second derived class:
class D : public A {
public:
D(int bar) { foo = bar; }
int method() { return foo+1; }
};
I'd like C to be able to take either B or D and my best assumption would be to take an A and let it handle it.
How do I use polymorphism correctly in this fashion?
Expected output with the below:
int main(void) {
C boo(B(1));
C boz(D(2));
std::cout << boo.get().method() << std::endl;
std::cout << boz.get().method() << std::endl;
return 0;
}
Would be:
1
3
First of all, in order to use A polymorphically, you need to add a virtual destructor, otherwise you will run into undefined behavior when trying to destroy the object. Then the method that you want to call through A must be virtual as well. If it shouldn't have an implementation in the base class itself, make it pure virtual:
class A {
protected:
int foo;
public:
virtual ~A() {}
virtual int method() = 0;
};
Then in C you need to use pointers or references to A, since polymorphism only works with those.
If you want C to own the A, as your code example to suggest, then you need to provide a destructor deleting the pointer and you need to disable copying of the class (or decide on some useful semantics for it):
class C {
private:
C(const C&); // Don't allow copying
C& operator=(const C&); // Don't allow copying
A* baz;
public:
C(A* faz) : baz(faz) { }
~C() { delete baz; }
A& get() { return *baz; }
};
int main(void) {
C boo(new B(1));
C boz(new D(2));
std::cout << boo.get().method() << std::endl;
std::cout << boz.get().method() << std::endl;
return 0;
}
Ideally you would upgrade to C++11 and use std::unique_ptr<A> instead of A* as member. But even if you can't do that, consider using boost::scoped_ptr<A>, which will manage the deletion for you (you don't need the destructor) and will make the class non-copyable by default. It also provides better exception-safety to encapsulate allocations in smart pointers like that.
If you need to call method() of type B using base class type A there has to be lookup during the runtime. The lookup is necessary to answer the question: Which method should be called? - the one that corresponds the type in a current line? Or other method in inheritance hierarchy?" If you expect method() from class B to be called when you have pointer or reference to A then you have to create a lookup table. This table is called vtable (from virtual functions table) and it's defined by adding virtual keyword to functions.
#include <iostream>
class A {
public:
virtual ~A(){}
virtual int method() = 0;
protected:
int foo;
};
class B : public A {
public:
B(int bar) { foo = bar; }
int method() {
std::cout << "Calling method() from B" << std::endl;
return foo; }
};
class C {
private:
A* baz;
public:
C(A* faz) { baz = faz; }
A* get() { return baz; }
};
int main(void) {
A* element = new B(1);
C boo(element);
boo.get()->method();
return 0;
}
It prints "Calling method() from B". Please keep in mind that the code is for presentation purposes and it's not good from best practices perspective.
I have the following code sample:
class A
{
public:
A(int a):AA(a) {};
int AA;
virtual int Test()
{
return AA;
};
};
class B
{
public:
B(int b):BB(b) {};
int BB;
virtual int Test()
{
return BB;
};
};
class C:public A, public B
{
public:
C(int a, int b, int c) :A(a),B(b),CC(c) {};
int CC;
};
int main()
{
A *a = new C(1,2,3);
B *b = new C(1,2,3);
C *c = new C(1,2,3);
int x = a->Test() ; // this is 1
int y = b->Test() ; // this is 2
// int z = c->Test() ; // this does not compile
return 0;
}
I was expecting the calls to a->Test() and b->Test() to be ambiguous too as the object a is a C and therefore inherits from A and B both of whom have identical Test() functions. However, they both call the implementation which corresponds to the delcared type rather than the type that the object actually is.
Can anyone explain why these calls are not ambiguous?
Does C++ always behave this way?
In fact,a C instance is both a full A instance and a full B instance (so holds a copy of A methods & B methods)
Since a is a A* , the compiler will use the A virtual table copy that is inside of the C instance
Since b is a B* , the compiler will use the B virtual table copy that is inside of the C
instance
you cannot use C* since the compiler will not now which Test() method of A or B you want to call (since the C class holds both A::Test & B::Test symbols)
if you implement a C::Test() method, then it will be called both instead of A::Test() & B::Test() since method is virtual for both A & B.
Because A does not know anything about the existence of C.
Consider a slightly different scenario:
foo.h
class A { public: virtual void Test() {} };
void myFunction(A *a);
foo.cpp
#include "foo.h"
void myFunction(A *a) {
a->Test();
}
You would expect this to compile, I guess? But what if I later independently inherited from A, should that affect whether this code compiles?
I'm getting an error below in the class a declaring a new pointer of type b. Please help.
#include <iostream>
namespace B
{
class b;
}
class a
{
private:
B::b* obj_b;
public:
a(){}
~a(){}
void create()
{
b* obj_b = new b;
}
};
class b
{
private:
a *obj_a;
public:
b()
{
obj_a->create();
}
~b(){}
};
int main()
{
b obj;
return 0;
}
b* obj_b = new b;
And there is your problem. You can declare a pointer to a B because pointers are all the same size, but you cannot construct one or take one by value without providing the class definition to the compiler. How would it possible know how to allocate memory for an unknown type?
There were many errors in your code. These are related to forward declaration, fully qualified name usage etc.
namespace B
{
class b;
}
class a
{
private:
B::b* obj_b; // change 1 (fully qualified name)
public:
void create(); // change 2 (can't use b's constructor now as B::b is not
// yet defined)
a(){}
~a(){}
};
class B::b // change 3 (fully qualified name)
{
private:
a *obj_a;
public:
b()
{
obj_a->create();
}
~b(){}
};
void a::create() // definition of B::b's constructor visible now.
{
B::b* obj_b = new B::b; // And here also use fully qualified name
}
int main()
{
B::b obj;
return 0;
}