Member acces into incomplete type C++ - c++

I am trying to have two classes in C++ - class1, class2. I want class2 to contain an instance of class1 and class1 to have a shared_ptr to the class2 – a pointer to the object, in which it is contained.
So I have following 4 files:
class2.hpp
#include "class1.hpp"
#include <vector>
class class2 {
friend class1;
private:
class1 data;
std::vector<int> numbers;
public:
class2();
};
class2.cpp
#include "class2.hpp"
class2::class2() : data(std::shared_ptr<class2>(this)){}
class1.hpp
#include <memory>
class class2;
class class1 {
std::shared_ptr<class2> ptr;
class1(std::shared_ptr<class2> ptr);
void add_item(int i);
};
and class1.cpp
#include "class1.hpp"
class1::class1(std::shared_ptr<class2> ptr) {
ptr = ptr;
}
void class1::add_item(int i) {
ptr->add_item(6); //Member access into incomplete type 'std::__1::shared_ptr<class2>::element_type' (aka 'class2')
}
I am getting the error in function add_item. I think that it has something to do with the forward declaration of class2.
I found this related topic, but there they dont split the files into header file.
error: member access into incomplete type : forward declaration of
If I understand well, I should put the function add_item after definition of class2, but I dont how to solve it, if I want to have the files splitted like this. Is it possible?
Please note, that I am trying to solve this in bigger project, this is very simplified.
Thanks is advance for any answer.

Forward declare class1 in class2.hpp and include class2.h in class1.cpp.
class2.hpp:
//#include "class1.hpp" // REMOVE!
#include <vector>
class class1; // ADD
class class2 {
...
class2.cpp:
#include "class2.hpp"
#include "class1.hpp" // ADD
class1.hpp:
#include <memory>
class class2; // OK
class1.cpp:
#include "class1.hpp"
#include "class2.hpp" // ADD
class1::class1(std::shared_ptr<class2> ptr) {
ptr = ptr;
}

I want class2 to contain an instance of class1 and class1 to have a shared_ptr to the class2 – a pointer to the object, in which it is contained.
No, you should not want that. There is no reason for a sub-object to own (even in shared capacity) their super object.
Furthermore, you cannot access members of an incomplete class. You must define the class first.

Related

Error in initializing new object in other class using "this" pointer of the other

I have two classes: SessionCardsMode and SetOfCards. SessionCardsMode takes in its constructor pointer to object of SetOfCards. When I try to create dynamically new SessionCardsMode object in SetOfCards method initializing it with this pointer I get information: "Cannot initialize type 'SessionCardsMode' with rvalue of type 'SetOfCards*'". It looks like I haven't proper constructor, but I have provided it. I don't know why it doesn't work. The problem is in SetOfCards::getSessionCards method in the first line of it. I've found that if I try to create the same object in body of class SessionCardsMode using identical statement everything works fine, but if I try to make it out of class I get the error.
//////////////////////////////SesionCardsMode.h
#pragma once
#include "Card.h"
#include "SetOfCards.h"
class SessionCardsMode
{
protected:
SetOfCards* m_setData;
std::forward_list<Card*> m_sessionSet;
public:
explicit SessionCardsMode(SetOfCards* set) : m_setData(set) {};
virtual Card* getCard();
//allows making combination of set setup by mixing classes that derives
//from ModeOfSet
void addAndShuffle(const SessionCardsMode* mode);
};
///////////////////////////////SetOfCards.h
#pragma once
#include "Card.h"
#include "SessionCardsMode.h"
class SetOfCards
{
private:
std::vector<Card> m_cardSet;
std::string m_setName;
public:
SetOfCards()=default;
explicit SetOfCards(std::string setName);
template<typename Iter>
SetOfCards(Iter begin, Iter end, std::string setName);
SessionCardsMode* getSessionCards(std::vector<CreatorAndInitVal> creators);
};
////////////////////////////////////////SetOfCards.cpp
#include "SetOfCards.h"
SessionCardsMode* SetOfCards::getSessionCards(
std::vector<CreatorAndInitVal> m_sessionCardsCreators)
{
SessionCardsMode* sessionCards=new SessionCardsMode(this); // error here
return sessionCards;
}
I don't understand why you don't get an error when you declare the constructor of SessionCardsMode (when you are compiling SetOfCards.cpp) - as far as I can see, at that point, SetOfCards is not defined.
Anyway, the solution to your problem is not to #include any of the headers in other headers, but to declare (not define) the other classes. So:
//////////////////////////////SesionCardsMode.h
#pragma once
class Card;
class SetOfCards;
class SessionCardsMode
{
protected:
SetOfCards* m_setData;
std::forward_list<Card*> m_sessionSet;
public:
explicit SessionCardsMode(SetOfCards* set) : m_setData(set) {};
...
};
///////////////////////////////SetOfCards.h
#pragma once
class Card;
class SessionCardsMode;
#include <vector> // You need this
#include <string>
class SetOfCards
{
private:
std::vector<Card> m_cardSet;
std::string m_setName;
public:
SetOfCards()=default;
explicit SetOfCards(std::string setName);
...
};
////////////////////////////////////////SetOfCards.cpp
#include "SetOfCards.h" // This should always be first
#include "..." // You'll probably need some more here.
SessionCardsMode* SetOfCards::getSessionCards(
std::vector<CreatorAndInitVal> m_sessionCardsCreators)
{
SessionCardsMode* sessionCards=new SessionCardsMode(this); // Error should be fixed
return sessionCards;
}

Pass a C++ struct pointer from one class to another one

I've two different classes (class1 class2) both of them have their own header and cpp files. Class2 has included the header of class1. Class1 has two structures which are public.
I want to call a method from class2 in class1 and to pass two pointers pointing on the structures.
The call of the method from class2 in class1. (obj is an object of class2 in class1):
obj.routine(ip_s.c_str(), &NLP_data_recv, &recv_data_data); //write to harddrive
Following the declaration of the method in class2:
int routine(std::string raw_data_re, struct NLP_data_header_package *Header_data, struct NLP_data_data_package *Data_data);
The following Error occurs:
“argument of type ""com::NLP_data_data_package *"" is incompatible with parameter of type ""NLP_data_data_package *""
How can I solve this problem? Thank you.
EDIT: Additional code:
class com header(class1):
#ifndef COM_H
#define COM_H
//...
#include "Dateiverwaltung.h"
//...
class com
{
private:
Dateiverwaltung obj;
//...
public:
int run(void);
com(std::array<std::string,TWO> socket);
~com();
struct NLP_data_header_package
{
//...
}NLP_data_recv;
struct NLP_data_data_package
{
//...
}recv_data_data;
class com cpp (class1)
//...
if (recv_command == DATA_COMMAND)
{
obj.routine(ip_s.c_str(), &NLP_data_recv, &recv_data_data); //write to harddrive
obj.ext_close_file();
}
//...
class Dateiverwaltung header(class2)
#ifndef DATEIVERWALTUNG_H
#define DATEIVERWALTUNG_H
//...
#include "communication.h"
//...
public:
Dateiverwaltung(char* directory_global_re);
~Dateiverwaltung();
int routine(std::string raw_data_re, struct NLP_data_header_package *Header_data, struct NLP_data_data_package *Data_data);
int ext_close_file(void);
//...
class Dateiverwaltung cpp (class2)
//...
int Dateiverwaltung::routine(string raw_data_re, struct NLP_data_header_package *Header_data, struct NLP_data_data_package *Data_data)
{
//...
The error says there's a "com::NLP_data_data_package"
and a "NLP_data_data_package"
That's two different classes (for the compiler), since they seem to be defined in different namespaces, namely com and the default namespace.

how to declare and use another class's object within a class in c++

I a beginner in programming.
I coded two classes(having constructors with requirement to pass arguments) and want to declare and use one class's object in another class.
I have tried to find the solution to my error on many website, but none of them worked. I also saw a solution to this problem using the 'new' syntax.
Please suggest some(any) way to sought out this problem.
A short program similar the one in which I am facing problems is as follows:
(I know this program is stupid but, this is not actual program I am facing problem in. Instead this is a narrowed down version of the part of the program in which I am facing error)
The error is in Class2.h and main.cpp
main.cpp
#include <iostream>
#include "Class2.h"
using namespace std;
int main()
{
Class2 Class2_Obj;
Class2_Obj.Class2_Function(); // error: undefined reference to `Class2::Class2_Function
return 0;
}
Class1.h
#ifndef CLASS1_H_INCLUDED
#define CLASS1_H_INCLUDED
class Class1
{
private:
const int c1_Variable;
public:
Class1(int);
// Displays the value of c1_Variable on output screan
void Class1_Function();
};
#endif // CLASS1_H_INCLUDED
Class1.cpp
#include <iostream>
#include "Class1.h"
Class1::Class1(int receivedInt) : c1_Variable(receivedInt) {}
void Class1::Class1_Function()
{
cout << c1_Variable;
}
Class2.h
#ifndef CLASS2_H_INCLUDED
#define CLASS2_H_INCLUDED
#include"Class1.h"
class Class2
{
private:
Class1 Class1_Obj(4); // 4 is just a random number.
//error: expected identifier before numeric constant
//error: expected ',' or '...' before numeric constant
public:
// Calls Class1_Function()
void Class2_Function();
};
#endif // CLASS2_H_INCLUDED
Class2.cpp
#include <iostream>
#include "Class1.h"
#include "Class2.h"
void Class::Class2_Function()
{
Class1_Obj.Class1_Function();
}
Here are the links to snapshots of the errors:
Screenshot of Error in Class2.h - http://i.stack.imgur.com/WpK9k.jpg
Screenshot of Error in main.cpp - http://i.stack.imgur.com/yDBD7.jpg
Please help me out! Thanks in advance for any responses :)
The issue is that this in-place initialization of non-static data members syntax is invalid:
class Class2
{
private:
Class1 Class1_Obj(4);
....
};
You can use {} instead,
class Class2
{
private:
Class1 Class1_Obj{4};
....
};
or this form
class Class2
{
private:
Class1 Class1_Obj = Class1(4);
....
};
C++ is a Object Oriented Language. It has classes to structure its data.
To put one class into another, you make an object of one class a member of another class.
Syntactically, it works like
class A {
int x;
public:
A (int x1) : x(x1) {}
};
class B {
A a; // this is how you do it ..
public:
B() : A(4) {}
};
B b; // b is an object which has a member b.a
As you can see, b is an object of class B. It has a member a of class A.

C++ multiple file error

i have been attempting to pass an object into a function that belongs to a class both classes are in there own files...but when i try to pass the object as an argument for the function prototype it gives me an error saying that the object doesn't exist... ill provide some pseudo code to demonstrate my problem
//class 1 .h
class Class1
{
public:
void function(Class2);//this is were one of my errors
};
//class 1 .cpp
void Class1::function(Class2 object )//another error
{
//stuff happens
}
//main.cpp
//then i simply call these functions like this
Class1 object;
Class2 object2;
int main()
{
object.function1(object2);
return 0;
}
and i get errors "Class2' has not been declared"
and errors about Class1 prototype does not match any classes....
if someone could explain what im doing wrong it would be a great help also if more code is needed just ask and i will post it.
EDIT
when i was attempting to include class2`s header in class one i was using the wrong director as i forgot i had separated .h files into there own folder anyway now i have fixed that it all work thanks a lot everybody.
You'll need to include Class2's header file in Class1.h. That is:
//////////////////
//Class1.h
#include "Class2.h"
class Class1
{
public:
void function(Class2 arg);
};
If you are only using a pointer to Class2 as an argument, then you can forward declare Class2 instead of including the header, that is:
//////////////////
//Class1.h
//Forward declare Class2 so the compiler knows the name exists
class Class2;
class Class1
{
public:
void function(Class2 *arg);
};
There's some more info here if you're interested.
Well, in fact Class2 has not been declared!
So,
// Class2.h:
class Class2
{
};
// Class1.h:
#include "Class2.h"
class Class1
{
public:
void function(Class2 object);
};
// Class1.cpp:
#include "Class1.h"
void Class1::function(Class2 object)
{
//stuff happens
}
// main.cpp:
#include "Class1.h"
Class1 object;
Class2 object2;
int main()
{
object.function1(object2);
return 0;
}
Have you tried doing this yet?
main.cpp:
#include "class1.h"
...
int main()
{
Class1 object;
Class2 object2;
object.function1(object2);
return 0;
}
The trick is to use the #include "class1.h" at the top of your main.cpp file
Actually you need to make the compiler aware of the classes that u are going to use in the file anywhere.
Have a look at a very similar Question : http://www.gamedev.net/topic/553424-c-calling-member-of-another-class-in-another-file/

Two classes and inline functions

I have two classes and both of them uses some of the other class, on example:
// class1.h
class Class1;
#include "class2.h"
class Class1 {
public:
static Class2 *C2;
...
};
// class2.h
class Class2;
#include "class1.h"
class Class2 {
public:
static Class1 *C1;
...
};
And when I define it like in example above, it works (I also have some #ifndef to avoid infinite header recurency). But I also want to add some inline functions to my classes. And I read here that I should put definition of inline function in header file, because it won't work if I'll put them in cpp file and want to call them from other cpp file (when I do it I get undefined reference during linking). But the problem here is with something like this:
// class1.h
...
inline void Class1::Foo() {
C2->Bar();
}
I get error: invalid use of incomplete type ‘struct Class2’.
So how can I do it?
You need to delay including the header, but then include it and define your inline methods. By doing this in each header, they are self-sufficient and including one will always include the other, with include guards preventing infinite recursion.
A.hpp
#ifndef INCLUDE_GUARD_B9392DB18D114C1B8DFFF9B6052DBDBD
#define INCLUDE_GUARD_B9392DB18D114C1B8DFFF9B6052DBDBD
struct B;
struct A {
B* p;
void foo();
};
#include "B.hpp"
inline
void A::foo() {
if (p) p->bar();
}
#endif
B.hpp
#ifndef INCLUDE_GUARD_C81A5FEA876A4C6B953D1EB7A88A27C8
#define INCLUDE_GUARD_C81A5FEA876A4C6B953D1EB7A88A27C8
struct A;
struct B {
A* p;
void bar();
};
#include "A.hpp"
inline
void B::bar() {
if (p) p->foo();
}
#endif
You have it mix'd up. What you want is:
// class1.h
class Class2;
class Class1 {
public:
static Class2 *C2;
...
};
// class2.h
class Class1;
class Class2 {
public:
static Class1 *C1;
...
};
And include the respective headers in the source. The line:
class Class1; // or Class2
Declares an incomplete type, and you can have pointers and references to incomplete types. Upon usage, though, it needs to be complete. So just say "hey it'll exist!" in the header, and in the source tell it what it is.
My suggestion is that you place common methods and members into a base class, then derive C1 and C2 from the base class. This may fix the circular dependency issue.