Reputation: 439
Following my previous question. I've settled on using using
directives to alias types inside my classes to avoid importing other stuff and polluting other headers that use these offending headers.
namespace MyLibrary {
namespace MyModule1 {
class MyClass1 {
public:
float X;
float Y;
MyClass1(float x, float y): X(x), Y(y) {}
};
} // namespace MyModule1
namespace MyModule2 {
class MyClass2 {
private:
// as suggested in linked question
using MyCustomType1 = MyLibrary::MyModule1::MyClass1;
public:
void DoSomething(MyCustomType1 parameter) {
std::cout << parameter.X << std::endl;
std::cout << parameter.Y << std::endl;
}
};
} // namespace MyModule2
} // namespace MyLibrary
int main(int argc, char* argv[])
{
MyLibrary::MyModule1::MyClass1 some_parameter(1.0f, 2.0f);
MyLibrary::MyModule2::MyClass2 some_var;
// Can't do this
// MyLibrary::MyModule2::MyClass2::MyCustomType1 some_other_var;
// But I can do this
some_var.DoSomething(some_parameter);
return 0;
}
How will the users outside of the MyLibrary
namespace know what is MyCustomType1
if it is aliased inside a class (privately)?
Is my usage here of using
legal, or is this a dirty hack I'm accidentally doing?
Upvotes: 0
Views: 77
Reputation: 118352
They will know for the simple reason you have to #include
the declarations of both classes.
Having read this, and the previous question, I think the missing concept here is the concept of forward declarations.
Consider the following header file, let's called this file mymodule1_fwd.H
:
namespace MyLibrary {
namespace MyModule1 {
class MyClass1;
} // namespace MyModule1
}
That's it. This is sufficient for you to declare MyClass2
:
#include "mymodule1_fwd.H"
namespace MyModule2 {
class MyClass2 {
private:
// as suggested in linked question
using MyCustomType1 = MyLibrary::MyModule1::MyClass1;
public:
void DoSomething(MyCustomType1 parameter);
};
} // namespace MyModule2
Note that including this header file only will not really automatically get the entire MyModule
class declaration. Also note the following:
You can't define the contents of the inline DoSomething
() class method, because it actually uses the aliased type. This has the following consequences:
You have to define the DoSomething
() method somewhere, in some way, probably inside the .C
implementation translation module.
Similarly, you have to have declare the actual MyClass1
class from the mymodule1_fwd.H
header file. I am using my own personal naming convention here, "filename_fwd.H" for forward declarations, the forward declaration header file; and "filename.H" for the actual class implementation, the implementation header file.
Callers of the DoSomething
() method will have to explicitly #include
the actual class declaration header file for MyClass
, since they have to pass it as a parameter.
You can't really avoid the fact that the callers have to know the class that they're actually using to pass parameters. But only the callers of the DoSomething
() method will need that. Something that uses other parts of the MyClass2
, and don't invoke DoSomething
(), don't need to know anything about MyClass1
, and the actual class declaration won't be visible to them unless they explicitly #include
the class implementation header file.
Now, if you still need DoSomething
() to be inlined, for performance reasons, there are a couple of tricks that can be used, with preprocessor directives, that if someone #include
s all the necessary header files, they'll get the inlined declaration of the DoSomething
() method.
But that'll have to be another question.
Upvotes: 1