Hai
I have a class A,B,C now i have member function in class A which needs the objects of
class B,C. Is it possible to achieve. If yes how?
class A
{
public:
void fun(B obj_b,C obj_c)
{
}
}
class B
{
//some work
}
class C
{
//some work
}
int main()
{
B obj_b;
C obj_c;
A obj_a;
obj_a.fun(obj_b,obj_c); //I GET ERROR HERE DURING COMPILATION
}
What is wrong in the above code?.
ERROR:
note: synthesized method first required here
error: initializing argument 1 of ‘void A::fun(B,C)’
Thank you
If it's not a typo : Your function fun is ill-formed, the return type is missing.
void fun(B obj_b,C obj_c) // void was missing
{
}
And as other pointed, there are several other problem with this code as missing return type for main, missing ; for class definitions, class B and class C must be declared before class A...
This last one seems to be what your error says.
Might be because of class declaration..
At void fun(B obj_b,C obj_c) the compiler has no idea about class B and class C. So try giving like
class B
{
//some work
};
class C
{
//some work
};
class A
{
public:
void fun(B obj_b,C obj_c)
{
}
};
If the classes are in different header files, #include them in class A..
Hope it helps..
The classes B and C are unknown in the void fun(B obj_b,C obj_c) line, you have to declare them first.
Either declare and define them first, if this is not possible (e.g. because they also need A), you can use forward declarations. It's just two single lines
class B;
class C;
BTW: With the method declaration void fun(B obj_b,C obj_c) you pass the parameters per value, what means that the objects B and C are copied. Most of the time this is not what u want: Pass them by reference by changing the method signature to void fun(B& obj_b,C& obj_c) .
After you correct all the syntax errors, you may encounter an error for the line declaring the fun member function, saying that the classes B and C are not yet declared. Place a forward declaration for classes B and C before the A class declaration. That is, something like:
class B;
class C;
class A
{
public:
void fun(B obj_b, C obj_c)
... other stuff here
};
class B
{
... real declaration of the class B
};
class C
{
... real declaration of the class C
};
By the way, forward declarations are the only method of circularly-referenced class declarations.
Related
Problem Summary
I'm attempting to write a series of classes in C++ 14, that are all supposed to be inside of the same class, and have pointer fields that point to object instances of each one of the classes. They are all also supposed to have constructors that assign those fields, using arguments that are pointers to the other class instances. I'm running into a problem where I am unable to call the constructor with the pointer arguments. Below is an illustration of my problem:
Defined in header file:
class A;
class B;
class C;
class A {
public:
class B {
public:
B(C* arg) {
ptr = arg;
}
C* ptr;
};
class C {
public:
...
};
};
Runner code in cpp file:
A::C TEST_C = *new A::C();
A::B TEST_B = *new A::B(&TEST_C);
The line which initializes TEST_B with the constructor pointer argument call gives the following two errors in the VS 2019 compiler:
Error C2664 'A::B::B(C *)': cannot convert argument 1 from 'A::C *' to 'C *'
Error C2512 'A::B': no appropriate default constructor available
My Attempts
The first error line got me thinking that I may need to change my forward class declarations to include their respective parent classes too, as such:
class A;
class A::B;
class A::C;
However, that appears to break the reference to class C completely, and any references to it in the header above it's definition treat it as an undefined reference (Identifier "C" is undefined.). It's as if there were no forward declarations at all.
Adding A:: to each reference to class C in the rest of the header as such:
class A {
public:
class B {
public:
B(A::C* arg) {
ptr = arg;
}
A::C* ptr;
};
class C {
public:
...
};
};
didn't help either, instead the compiler tells me Class "A" has no member "C"..
However, one interesting thing that I did notice, was the fact that if I change the argument being passed to the constructor call for class B, to nullptr, that is:
A::B TEST_B = *new A::B(nullptr);
then the code gets compiled without problems. To me, that meant that this is most likely an issue with my forward class declarations, where the compiler sees that there are classes B and C declared, but it doesn't get to reading the actual content of the classes prior to attempting to reference them.
Is what I'm trying to accomplish here even possible with C++? Is there a way I should be doing this properly, that I'm not seeing?
Thank you in advance for reading my post, any help is appreciated!
The problem is that you've forward declared class C in global namespace instead of class scope A. This means that there are two different class named C one of which is declared to be in the global namespace ::C and the second one as an inner class A::C.
To solve this, just move the forward declaration of class C to inside class scope A as shown below:
header.h
class A {
public:
class C;// forward declaration moved here inside class scope A
class B {
public:
B(C* arg) {
ptr = arg;
}
C* ptr;
};
class C {
public:
};
};
Working demo
Also, be careful about other logical bugs like memory leak(if any) in your program.
class A {
public:
class C;
class B {
public:
B(C* arg) {
ptr = arg;
}
C* ptr;
};
class C {
public:
...
};
};
I think the question title may be impossible to get right but, I have a class (lets call it A) which has a constructor that needs a pointer to another class (called B). This would be fine but when I define a class in a third class (called C), then I get this error after putting a variable into the constructor: error: expected identifier before ‘&’ token, then if I remove the & I get: error: ‘ClassA’ is not a type.
For those who can't understand what I just said (I don't blame you), here is an example:
class A
{
private:
int number;
//etc, etc...
};
class B
{
private:
A* ClassAPntr;
public:
B(A* objectPointer)
{
ClassAPntr = objectPointer;
}
};
class C
{
private:
A ClassA;
B ClassB(&ClassA);
};
int main()
{
C classC;
}
You didn't actually declare a constructor for class C. What you meant to do was this:
class C
{
public:
C()
: b(&a) // you have to provide the arguments to B's constructor here
{ }
private:
A a;
B b; // ... not here
};
Just for clarification, when you did composition by adding A classA private object to class C, the compiler accept this step because A has undefined constructor which means the compiler will make a default constructor for you and call it when make A classA.
The problem in class B because it has a non-default user defined constructor which means that compiler should force you to call it in class C through constructor initialization list or through curly braces in c++11, so it becomes your responsibility simply because compiler can't know which address for which class A Object you are going to pass for class B
constructor.
So why did you get this error message : class A is not a type or expected identifier before ‘&’ token?
the answer is that compiler considered B ClassB(&ClassA) a declaration for a private function with name ClassB and a return value of type B class.
and because you never use this function in your class the compiler will never give you any error related to definition. and you will also never use this member function in other functions like main because it is private
to produce the undefined reference error you can modify c class to be like this:
class C
{
private:
A classA;
B classB();
friend B func() ;
};
B func() {
C c;
return c.classB(); // undefined reference Error
}
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'm pretty new at using C++ and I'm actually stopped at a problem.
I have some class A,B,C defined as follow (PSEUDOCODE)
class A
{
...
DoSomething(B par1);
DoSomething(C par1);
...
}
class B
{
A parent;
...
}
class C
{
A parent;
...
}
The problem is :
How to make this? If I simply do it (as I've always done in c#) it gives errors. I pretty much understand the reason of this. (A isn't already declared if I add the reference (include) of B and C into its own header)
Any way to go around this problem? (Using void* pointer is not the way to go imho)
Forward-declare B and C. This way compiler will know they exist before you reach the definition of class A.
class B;
class C;
// At this point, B and C are incomplete types:
// they exist, but their layout is not known.
// You can declare them as function parameters, return type
// and declare them as pointer and reference variables, but not normal variables.
class A
{
....
}
// Followed by the *definition* of B and C.
P. S.
Plus, one more tip unrelated to the question (seeing how you come from a C# background): it's better to pass by const reference than by value:
class A
{
...
void DoSomething(const B& par1);
void DoSomething(const C& par1);
...
}
For function declarations, parameter types are allowed to be incomplete if the function is not defined there:
class B;
class C;
class A
{
...
R DoSomething(B par1);
R DoSomething(C par1);
...
}
class B
{
A parent;
...
}
class C
{
A parent;
...
}
inline R A::DoSomething(B par1) { ... }
inline R A::DoSomething(C par1) { ... }
So you just define them after B and C become complete. But since they are defined outside the class, make them inline so multiple definitions in different translation units won't cause linker errors.
You should forward declare classes B and C before A:
class B;
class C;
class A {
...
};
At the point where B and C are referenced within A, the compiler only needs to know what kind of animals these are. With the forward declaration you satisfy the compiler. Then later you can define them properly.
use forward declaration
You can define class A; without it's implementation, before B and C, and then define it later
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.