I have two classes inside one cpp file like this:
class A
{
private:
int somethingPrivate;
B *aReferenceToB;
public
B returnSomeB()
{
aReferenceToB->someFunction();
return *aReferenceToB;
}
};
class B
{
private:
A needed_Class_A_var;
public:
void someFunction()
{
return;
}
};
This ciclic use of these two classes, one inside another, generates all sort of errors like
error C2143: syntax error : missing ';' before '*'
How can I resolve this ciclic include problem without creating separate files for each class and using only one cpp file?
I have tried to add a class B; declaration before class A definition wich does not work properly.
Before you access members of the B class (aReferenceToB->someFunction()), or even try to return the object of B (not the pointer to B) (B returnSomeB), you need to have a complete definition of class B first.
So, just extract the returnSomeB body out of the class A definition, and put it in place where the full definition of B is known.
class B;
class A
{
private:
int somethingPrivate;
B *aReferenceToB;
public:
B returnSomeB();
};
class B
{
private:
A needed_Class_A_var;
public:
void someFunction()
{
return;
}
};
B A::returnSomeB(){
aReferenceToB->someFunction();
return *aReferenceToB;
}
Please note that if you try to write something like this:
class B;
class A
{
private:
int somethingPrivate;
B *aReferenceToB;
public:
B* returnSomeB() { return aReferenceToB; }
};
that would be valid, because you're only manipulating with the pointers here (in this case, you're not creating object of B, and you don't access any of B's members), and the size of the pointer is known at the compile time, even without class B definition.
Related
I have two classes like this:
class B;
class A {
public:
int a, b;
B *b;
public:
int getctxt()
{
b->getctxt1();
}
}
Class B {
public:
int c,d;
A *a;
getctxt1()
{
/* something */
}
}
main()
{
B *b = new B();
A *a = new A();
b->a = a;
a->b = b;
}
But when I try to compile, it says
invalid use of incomplete type ‘struct A’.
Can anyone tell me how to solve this?
Inline class member function definitions are parsed as if they appeared right after the class definition. Of course B isn't defined at that point. So move the member function definition for A::getctxt out of the definition of class A:
class B;
class A { int getctxt(); /* ... */ };
class B { /* ... */ };
int A::getctxt()
{
b->getctxt1(); // at this point, *b has complete type!
return -35;
}
This is the reason why it is recommended to separate your classes in a .h file and a .cpp file. When you write class B;, you are telling the compiler that there is a class called B, but that's it, the compiler does not know what is inside this class. When the compiler reaches the line b->getctxt1();, it knows that b is an instance of B, but it does not know if getctxt1() is a method of B, because that is below. If you are writing all in a single file, you should first write all the declarations, and then all the implementations.
didn't anyone notice Class B syntax error? lowercase class is correct.
and those two public members in A with the same name int b and B *b.
once you remove those and finish class definitions with semicolons, add a void type to the void getctxt1() that is missing it in B.
just define functions as they should be defined. not inline without a reason that you know which is!
I was trying to create a member (prop of class A) to a class (B). This member "prop" of class A needs to gets the "this" pointer of the newly created B-instance passed in its constructor. Just as shown in the snippet (Snippet 1) below.
However, this is failing at compile time with the error message:
"A typespecifier was expected" (translated from german).
I think this is about I am not able to use the this-pointer in this context, but I do not want to go the way of Snippet 2 and use a pointer. It is just not practical for me.
Is there any way to accomplish this close to the coding style of the first snippet?
Snippet 1
class B;
class A
{
public:
A(B* b)
{
// ...
};
};
class B
{
public:
A prop(this);
};
Snippet 2
class B;
class A
{
public:
A(B* b)
{
// ...
};
};
class B
{
public:
B()
{
this->prop = new A(this);
}
A* prop;
};
Edit: Just figured out this snippet, but when having many of them in one class makes it really unreadable.
Snippet 3
class B;
class A
{
public:
A(B* b)
{
// ...
};
};
class B
{
public:
B() : prop(this) {};
A prop;
};
Many thanks!
Sebastian
You cannot initialize class member in class declaration. As you correctly noted in snippet #3 - constructor initialization list exists for the members, that require parameters to be passed to constructor.
Using an initializtion list is the best way IMHO of doing this, note, members are initialized in the order you declare them, but not the order at initializer list:
class B
{
public:
B() : prop(this) {};
A prop;
};
I got the solution by myself now.
For non-experimental; non-c++11 standard, luri Covalisin is right.
But if we give a look at c++11, we can do as follows:
class B;
class A
{
public:
A(B* b)
{
// ...
};
};
class B
{
public:
A prop{this};
};
this looks kinda weird, but is more like what I was looking for.
I'm using this code in C++ CLI. However this shouldn't make any difference from C++.
I'm looking for a solution to get rid of that error.
Code :
ref class B;
ref class A;
public ref class A
{
public:
A() {}
B^ b;
void HelloFromA(){
b->HelloFromB();
}
};
public ref class B
{
public :
A^ a;
B() {}
void HelloFromB(){
a->HelloFromA();
}
};
You need to move the bodies of the functions that invoke member functions on the forward-declared classes outside of the headers, to places where definitions are available:
void A::HelloFromA(){
b->HelloFromB();
}
Otherwise, the compiler knows that B is available, but it does not know that B has the HelloFromB member function that takes no arguments.
I have defined a class A and derived a new class B from A .
I have overloaded SetData() function in class B.
When I tried to access SetData function of class B using object of B, compiler doesn't permit it. Why is it so ?
class A{
public :
void SetData();
};
class B : public A {
public:
void SetData(int);
};
B b;
b.SetData() ; // error
OMG, no error message. -1 for you.
But let us use telepathy and guess your error message. You're getting something like "symbol not found" because you try to call a function B::SetData() which doesn't have a body. And it must have a body even if it does nothing and even if it's declared in parent class! Try adding it into the body of your class
class B : public A {
public:
void SetData(int)
{ /* add body here */ };
};
or outside of it
class B : public A {
public:
void SetData(int);
};
void B::SetData(int)
{
//write it here
}
b.SetData(2) ; // error
I don't see any problem in calling SetData(2).
Where as if you call b.SetData() ; then there will be an error. When you define a method with same name in in derived class the base class methods with same name will be hidden in derived class.
You can make them visible in derived class by using keyword.
class A{
public :
void SetData(){}
};
class B : public A {
public:
using A::SetData;
void SetData(int){}
};
int main()
{
B b;
b.SetData() ; // error
}
What i guess you might be facing
error: unresolved external symbol
write code as suggested by Pavel Shved
Is there anyway to declare an object of a class before the class is created in C++? I ask because I am trying to use two classes, the first needs to have an instance of the second class within it, but the second class also contains an instance of the first class. I realize that you may think I might get into an infinite loop, but I actually need to create and instance of the second class before the first class.
You can't do something like this:
class A {
B b;
};
class B {
A a;
};
The most obvious problem is the compiler doesn't know how to large it needs to make class A, because the size of B depends on the size of A!
You can, however, do this:
class B; // this is a "forward declaration"
class A {
B *b;
};
class B {
A a;
};
Declaring class B as a forward declaration allows you to use pointers (and references) to that class without yet having the whole class definition.
You can't declare an instance of an undefined class but you can declare a pointer to one:
class A; // Declare that we have a class A without defining it yet.
class B
{
public:
A *itemA;
};
class A
{
public:
B *itemB;
};
There's an elegant solution using templates.
template< int T > class BaseTemplate {};
typedef BaseTemplate< 0 > A;
typedef BaseTemplate< 1 > B;
// A
template<> class BaseTemplate< 0 >
{
public:
BaseTemplate() {} // A constructor
B getB();
}
// B
template<> class BaseTemplate< 1 >
{
public:
BaseTemplate() {} // B constructor
A getA();
}
inline B A::getB() { return A(); }
inline A B::getA() { return B(); }
This code will work! So, why does it
work? The reason has to do with how
templates are compiled. Templates
delay the creation of function
signatures until you actually use the
template somewhere. This means that
neither getA() nor getB() will have
their signatures analyzed until after
both classes A and B have already been
fully declared. That's the magic of
this method.
Is this close to what you want: The first class contains the second class, but the second class (that is to be created first) just has a reference to the first class?
This is called cross reference. See here an example.