Just read about friend functions and I'm trying to access private variable "number" in class A with friend function "Print" from class B. I'm working with Visual Studio. Compilation of my code gives me plenty of various errors like:
C2011: 'A' : 'class' type redefinition
C2653: 'B' : is not a class or namespace name
Please be patient with me me and show a proper way of achieving my goal.
Here are my files
A.h:
class A
{
public:
A(int a);
friend void B::Print(A &obj);
private:
int number;
};
A.cpp:
#include "A.h"
A::A(int a)
{
number=a;
}
B.h:
#include <iostream>
using namespace std;
#include "A.h"
class B
{
public:
B(void);
void Print(A &obj);
};
B.cpp:
#include "B.h"
B::B(void){}
void B::Print(A &obj)
{
cout<<obj.number<<endl;
}
main.cpp:
#include <iostream>
#include <conio.h>
#include "B.h"
#include "A.h"
void main()
{
A a_object(10);
B b_object;
b_object.Print(A &obj);
_getch();
}
... Second you might need a forward declaration of class B in the A.h header file to refer B as a friend:
#ifndef _A_H_
#define _A_H_
class B;
class A
{
friend class B;
};
#endif
UPDATE
I'm currently not so sure if it's possible to declare member functions as friends, I'll have a look.
It's not possible to create member function friend declarations, you can either declare global functions or whole classes as friend, see also: C++ ref, Friendship and inheritance.
In general it's not a good design idea to use friend at all, because it strongly couples the classes together. The better solution will be to couple interfaces (which don't need to be publicly visible anyways).
In rare cases it might be a good design decision but that almost always applies to internal details.
First you need to put
#ifndef A_H
#define A_H
.... your A-class definition
#endif
in your A.h and analogous in B.h, so that multiple includes of the same file is prevented (that is your duplicate definition error)...
Related
I'm starting to learn C++ and recently encountered a problem with circular dependency of two headers.
I've already tried forward declaring the Class and namespace, also played around with it in a seperate project but didn't find any solution. Whatever I do the function doesn't get access to the class private members.
Here i simplified the problem a little bit.
A.h
#pragma once
#include "B.h"
class Player {
private:
int m_number;
public:
friend void Byte::getDataChunk(Player& p);
};
B.h
#pragma once
#include <iostream>
#include "A.h"
class Player;
namespace Byte {
void doOtherStuff() {
//other Stuff
}
void getDataChunk(Player& p) {
std::cout << p.m_number;
doOtherStuff();
}
}
I would really like to keep the class and namespace in seperate files, but I don't see any way of doing it. Thanks for your help in advance!
You need to change A.h to include a forward declaration of getDataChunk() in namespace Byte:
#pragma once
#include "B.h"
class Player;
namespace Byte {
void getDataChunk(Player& p);
}
class Player {
private:
int m_number;
public:
friend void Byte::getDataChunk(Player& p);
};
Please note also that including function definitions in header files (i.e. getDataChunk() in B.h) is going to cause you headaches.
Hi I already read similar questions about this topic, but I coudn't resolve my problem.
I think I have to do a forward declaration so I tried the following.
I have three classes A, B and InterfaceA
Defintion InterfaceA
#ifndef INTERFACE_A_H
#define INTERFACE_A_H
#include "B.h"
namespace Example
{
class B; // Forward declaration?
class InterfaceA
{
Example::B test;
};
}
#endif
Definiton class A
#ifndef A_H
#define A_H
#include "InterfaceA.h"
namespace Example
{
class A : public Example::InterfaceA
{
};
}
#endif
Defintion class B
#ifndef B_H
#define B_H
#include "A.h"
namespace Example
{
class A; // Forward declaration?
class B
{
Example::A test;
};
}
#endif
main
#include "A.h"
#include "B.h"
int main()
{
Example::A a;
Example::B b;
}
I get the following error in visual studio:
'Example::B::test' uses undefined class 'Example::A'
Edit:
Thank you so far, for all the help. It was very helpful. I think my problem was that I had a very poor design in my real project. I will change that.
Beside that I have now a better understanding for forward declarations :-)
If you really need that class A references class B and viceversa, instead of having instances of A and B as data members, consider using pointers, e.g. something like this:
// A.h
#pragma once
#include <memory> // for std::unique_ptr
// Forward declaration (A references B using pointer)
class B;
class A
{
...
std::unique_ptr<B> m_pB;
};
And similarly:
// B.h
#pragma once
#include <memory> // for std::unique_ptr
// Forward declaration (B references A using pointer)
class A
class B
{
...
std::unique_ptr<A> m_pA;
};
PS
Not related to the core of your question, however note that I used #pragma once instead of "old style" #ifndef/#define/#endif include guards; #pragma once seems simpler and clearer to me.
You are creating circular dependency. Revise your design.
Do you really need an instance of class A inside B and B inside A?
make them both inherit from the same parent header file, if they need to share header information.
I have included the proper
Header Files ,
Header Gard
but i cannot instantiate a specific class
Getting Error
error C2065: 'ClassName' : undeclared identifier
Sample Code
Class A{
//instantiate class B
}
Class B {
//need to instantiate Class A
}
Since you haven't posted any real code for us to actually make use of, I'll take a guess as to what your code actually looks like:
A.h:
#ifndef HEADER_A
#define HEADER_A
#include "B.h"
class A {
private:
B someMember;
};
B.h:
#ifndef HEADER_B
#define HEADER_B
#include "A.h"
class B {
public:
doSomething(A param);
};
B.cpp:
#include "B.h"
#include "A.h"
void B::doSomething(A param) { }
As Flinsch said, you need to have forward declarations to avoid problems with include ordering. The simplest way is to get rid of the circular includes in the .h files and just include the forward declarations (class B; and class A; into A.h and B.h) instead.
btw. you don't have ; at the end of class definition.
Under my understanding there is a circular dependency between classes A and B. So you need to use forward declaration for at least one of those two classes (or even both).
This question already has answers here:
Resolve build errors due to circular dependency amongst classes
(12 answers)
Closed 4 years ago.
FILE #1 (foo.h):
#ifndef FOO_H_
#define FOO_H_
#include "baseclass.h"
#include "bar.h"
class Bar;
class Foo : public baseclass {
public:
bar *varBar;
};
#endif
FILE #2 (bar.h):
#ifndef BAR_H_
#define BAR_H_
#include "foo.h"
class Foo;
class Bar {
public:
Foo *varFoo;
};
#endif
FILE #3 (baseclass.h):
#ifndef BASECLASS_H_
#define BASECLASS_H_
#include "foo.h"
class Foo;
class baseclass {
public:
list<Foo*> L;
};
#endif
But I get an compile error in file #1 in line class Foo : public baseclass:
Error: expected class-name before »{« token
If I add class baseclass; bevor class declaration, I get this error:
Error: invalid use of incomplete type »struct baseclass«
So my question is, how can I resolve circular dependencies with baseclasses?
Ask if you don't get somepoint. I allready tried to change the order of includeing the headers, but no luck so far.
Thanks for any hint.
EDIT: Note: I am using include guards
EDIT2: It is not limited to pointers, so I remove them, just in case.
EDIT3: Added baseclass (forgot O.o)
EDIT4: Now it should be clear and without anymore flaws, the problem persisits with this code.
The usual way is to add the following around your header files:
#ifndef FOO_H_
#define FOO_H_
#include "baseclass.h"
#include "bar.h"
class Bar;
class Foo : public baseclass {
public:
bar *varBar;
};
#endif
and
#ifndef BAR_H_
#define BAR_H_
#include "foo.h"
class Foo;
class Bar {
public:
Foo *varFoo;
};
#endif
Most compilers (gcc, VC) also accept #pragma once at the beginning of the file, but I'm pretty sure it is not part of the current C++ standard.
EDIT:
Sure enough, as the ISO/IEC 14882 states, a #pragma "causes the implementation to behave in an implementation-defined manner. Any pragma that is not recognized by the implementation is ignored."
It is currently still the same with C++0x.
So I would stick with the first old-fashioned way of doing that ;-)
What you seem to have posted is to have a Bar member in the Foo, and a Foo member in the Bar. That is a circular dependency you need to break - if every Foo contains a Bar which contains a Foo then constructing either never terminates.
class Foo : public baseclass {
public:
Bar varBar;
};
class Bar {
public:
Foo varFoo;
};
Instead you need to use a pointer or reference to the Foo or Bar in at least one of them:
class Bar;
class Foo : public baseclass {
public:
Bar& varBar;
};
class Bar {
public:
Foo varFoo;
};
As the circularity is broken and you're only using a reference to the object, you don't need to have the full definition of the referred-to type, and can use a forward declaration.
Include guards are good for users, but try and not rely on them when developing. If the compiler has to check whether or not something has been included, it's still doing work even if it has optimisations for guards/pragmas. You do need to have some understanding of what depends on what to break the initial cycle, and putting guards on the files won't help you with that.
Do you have include guards on your headers? The code above includes a.h and b.h recursively, thus defining a whole bunch of headers.
The forward declaration class b; removes the need for the #include "b.h" in FILE1. Similarly, #include "a.h" should be removed from FILE2.
#ifndef _BAR_H_
#define _BAR_H_
#include "baseclass.h"
class Bar;
class Foo : public baseclass {
public:
Bar *varBar;
};
#endif
If a class is forward declared and you are using only a pointer or a reference to a member of that class, then you do not need to include the header for it. The same goes for the class in the other file. But yes, make sure that you use include guards in all of your header files (#ifndef...#endif) to prevent multiple inclusions of headers during compilation.
baseclass.h doesn't need anything from foo.h, so remove #include "foo.h" from baseclass.h.
You have a Foo variable in your Bar, and a Bar in your Foo. That isn't going to work: you can't have an egg in a box and a box in an egg. One or both of them should be a pointer.
I'm getting this error when dealing with a number of classes including each other:
error: expected class-name before '{' token
I see what is going on, but I do not know how to properly correct it. Here is an abstracted version of the code:
A.h
#ifndef A_H_
#define A_H_
#include "K.h"
class A
{
public:
A();
};
#endif /*A_H_*/
A.cpp
#include "A.h"
A::A() {}
B.h
#ifndef B_H_
#define B_H_
#include "A.h"
class B : public A
{ // error: expected class-name before '{' token
public:
B();
};
#endif /*B_H_*/
B.cpp
#include "B.h"
B::B() : A() {}
J.h
#ifndef J_H_
#define J_H_
#include "B.h"
class J
{
public:
J();
};
#endif /*J_H_*/
J.cpp
#include "J.h"
J::J() {}
K.h
#ifndef K_H_
#define K_H_
#include "J.h"
class K : public J
{ // error: expected class-name before '{' token
public:
K();
};
#endif /*K_H_*/
K.cpp
#include "K.h"
K::K() : J() {}
main.cpp
#include "A.h"
int main()
{
return 0;
}
Starting in main.cpp, I can determine that this is what the compiler sees:
#include "A.h"
#ifndef A_H_
#define A_H_
#include "K.h"
#ifndef K_H_
#define K_H_
#include "J.h"
#ifndef J_H_
#define J_H_
#include "B.h"
#ifndef B_H_
#define B_H_
#include "A.h"
class B : public A
{ // error: expected class-name before '{' token
So, A's definition is not complete when we get to B. I've been told that sometimes you need to use a forward declaration and then move the #include statement into the .cpp file, but I'm not having any luck with that. If I try anything like that, I simply get the additional error:
error: forward declaration of 'struct ClassName'
I think maybe I'm just not doing things in the right places. Can someone please show me how to get this code to compile? Thank you very much!
Edit: I want to point out that this is just abstracted version of the real code. I realize that there are no references to K in A or B in J, but there are in the real code and I feel that they're completely necessary. Perhaps if I give a brief description of the real classes, someone can help me restructure or fix my code.
Class A is an abstract node class that acts as an interface for nodes in a graph. Class B is one of what will be a number of different implementations of A. In the same manner, class J is an abstract Visitor class and K is the corresponding implementation. Here is the code with a little more context:
A.h (Abstract Node)
#ifndef A_H_
#define A_H_
#include "K.h"
class K;
class A
{
public:
A();
virtual void accept(const K&) const = 0;
};
#endif /*A_H_*/
A.cpp
#include "A.h"
A::A() {}
B.h (Concrete Node)
#ifndef B_H_
#define B_H_
#include "A.h"
class K;
class B : public A
{ // error: expected class-name before '{' token
public:
B();
virtual void accept(const K&) const;
};
#endif /*B_H_*/
B.cpp
#include "B.h"
B::B() : A() {}
void B::accept(const K& k) const { k.visit(this); }
J.h (Abstract Visitor)
#ifndef J_H_
#define J_H_
#include "B.h"
class B;
class J
{
public:
J();
virtual void visit(const B*) const = 0;
};
#endif /*J_H_*/
J.cpp
#include "J.h"
J::J() {}
K.h (Concrete Visitor)
#ifndef K_H_
#define K_H_
#include "J.h"
class B;
class K : public J
{ // error: expected class-name before '{' token
public:
K();
virtual void visit(const B*) const;
};
#endif /*K_H_*/
K.cpp
#include "K.h"
K::K() : J() {}
void K::visit(const B*) const {};
main.cpp
#include "A.h"
int main()
{
return 0;
}
I had to add some forward declarations to make some additional errors that appeared (when I added detail) go away. Some of them may not be necessary or correct.
Your header inclusions are circular. A -> K -> J -> B -> A. Using forward declarations is the simplest way to avoid such complexity, but it is only possible when the class being declared only uses references or pointers to the class being included. You can't use forward declaration in K.h or B.h, for example, because they inherit from J and A respectively. However, you may be able to replace the #include "K.h" in A.h with class K; depending on how you are actually using K in A.
Talk about confusing.
In this concrete example, remove the
#include "B.h"
from file J.h since it' s not needed there. If that doesn't work, we would need some more details about how J uses B...
EDIT
Since J only uses a pointer to B, the advice stays the same :-) :
Remove #include "B.h" from J.h and replace it by a forward declaration of B:
(J.h)
class B;
class J
{
// ...
virtual void visit(const B*) const = 0; // This will work with forward declaration
}
Also remove #include "K.h"from A.h.
IMPORTANT
Of course you need to add the needed includes in the respective CPP files:
(J.cpp)
#include "B.h"
// ...
// Go ahead with implementation of J
// ...
(Same for A.cpp, include K.h)
The main problem is that your header files include each other in a circular manner. A includes K which includes J which includes B which then includes A again... You should never require a situation where this happens. You should go back to the design drawing board and either cut some of the dependencies, or reorganize your classes entirely so that this circular dependency doesn't happen.
The problem is that your header files cyclically depend on each other. Don't include K.h in A.h and B.h in J.h. They aren't needed there.
Regarding your edit: this is not the best way for your objects to interact. Rethink your design. Who calls node.accept(visitor)? Can't you call visitor(node) directly?
Also, if you're trying to design a graph library, have a look at Boost.Graph library.
That said, since you only use a pointer to B in J.h, you don't have to include B.h, only forward-declare the class.
class B;
struct J
{
virtual void visit(const B*) const = 0;
};
Then include B.h in your K.cpp file.
#include "K.h"
#include "B.h"
void K::visit(const B* b) const
{
// use b here any way you want
}
Circular inclusions do not work.
Try to keep inclusions to a strict minimum. If you do that, you'll either be fine altogether, or you'll discover problems in your design. In your case, i don't see anything wrong with your design.
When defining class K, you're only using a pointer to an object of type B. That does not require B to be defined (as in "include the header file"), only to be declared (forward declaration is fine). So, in your case, removing inclusion to header "B.h" replaced by "class B;" is sufficient. (the same goes for class J)