I have 2 classes: MyString and LongNumber. And the LongNumber class has a Foo method that has access to the private fields of the MyString class, that is to say, the method Foo is a friend to the class MyString. So I wrote some code here:
// File: MyString.h
- - - - - - - - - - - - - -
#pragma once
// default includes with angular brackets
class LongNumber; // forward declaration
class MyString
{
char* symbols;
size_t capacity;
size_t length;
friend void LongNumber::Foo(MyString& str); // <-- error here
// Methods
}
// File: MyString.cpp
- - - - - - - - - - - - - -
// including "MyString.h" and "LongNumber.h" in .cpp to avoid circular dependency
#include "MyString.h"
#include "LongNumber.h"
// default includes with angular brackets
// Implementations
// File: LongNumber.h
- - - - - - - - - - - - - -
#pragma once
// default includes with angular brackets
class MyString; // forward declaration
class LongNumber
{
uint8_t sign;
MyString digits;
void Foo(MyString& str); // supposed to be a friend to the class MyString
// Methods
}
// File: LongNumber.cpp
- - - - - - - - - - - - - -
// including "MyString.h" and "LongNumber.h" in .cpp to avoid circular dependency
#include "MyString.h"
#include "LongNumber.h"
// default includes with angular brackets
void LongNumber::Foo(MyString& str) // supposed to be a friend to the class MyString
{
// some code
}
// other implementations
File: Main.cpp
- - - - - - - - - - - - - -
#include <iostream>
#include "MyString.h"
#include "LongNumber.h"
// #include "LongNumber.h"
// #include "MyString.h"
// reversed order won't help either
int main() {} // empty
I have read about avoiding circular dependencies in C++. They advise you to forward declare the class in the .h file, and to move all the include's to the .cpp file. I have done so, but this won't work for me.
When I compile this, I get: ...MyString.h(11,26): error C2027: use of undefined type 'LongNumber'
The line of code which causes this error is: friend void LongNumber::Foo(MyString& str);
The compiler does not care that I forward declared the class LongNumber. It almost seems that it does not see my other files in some sense, because if I modify the MyString.h file like this:
// File: MyString.h
- - - - - - - - - - - - - -
#pragma once
// default includes with angular brackets
class UnknownClass; // forward declaration, deliberately wrote a name that does not exist
class MyString
{
char* symbols;
size_t capacity;
size_t length;
friend void UnknownClass::Foo(MyString& str); // <-- error here
// Methods
}
The error is the very same: ...MyString.h(11,28): error C2027: use of undefined type 'UnknownClass'
I feel like the only way to let the compiler know that the class LongNumber exists and is completed is to put #include "LongNumber.h" into the header file, but that's not allowed, because it would create a circular dependency.
Is what I am trying to accomplish possible?
You cannot refer to a method of an incomplete class by its name. Make
UnknownClassaKnownClass:Circular dependency yes, but its not an issue, because
void KnownClass::foo(const MyString&);only needs a declaration ofMyString, but it doesnt needMyStringto be complete.