I have files MyClass.hpp and MyClass.cpp
MyClass.hpp
class MyClass {
public:
void method1();
void method2();
};
MyClass.cpp
#include "MyClass.hpp"
void MyClass::method1() {
}
void MyClass::method2() {
}
I find it a little silly that I have to write out the MyClass:: every time I have to write a method implementation. Is there some sort of syntactic sugar that lets me just group all my implementation together?
Perhaps something like
namespace MyClass {
void method1() {
}
void method2() {
}
}
I don't mind using C++11 features, but I would like to stick with portable solutions.
EDIT:
I realize that the code above as written wouldn't work. I was just using it as an illustration of how I imagine some syntactic sugar would work to make things more convenient.
No, it is not possible.
The only way is to define your member functions directly inside the class definition, which makes them inline and may or may not be what you want.
Personally, I reckon having function definitions in source files is well worth having to type out a class name once in each.
No, there is no other-way. You have to repeat MyClass::
It is not possible to identify a method using namespace. In a namespace there can be several classes, non-member methods .... Since a class method can be defined in any source file (other than the header declaring the class itself), you have to specify which class a method belongs to while defining it.
Related
When I have a C++ class MyClass in namespace mynamespace, I implement its methods as
void mynamespace::MyClass::method() { … }
I can wrap that in a namespace to shorten individual definitions to
namespace mynamespace {
void MyClass::method() { ... }
}
Is there a way to avoid having to retype MyClass:: as well so I can copy everything before the { to the header as a prototype more easily whenever the signature changes, without having to remove the MyClass:: every time?
I thought "a class is also a namespace, maybe I can do"
namespace mynamespace::MyClass {
void method() { ... }
}
but that complains that I was re-defining MyClass as a different thing. using mynamespace::MyClass; also didn't work (but would be bad anyway because how would I declare a standalone function anywhere below that line in that file if it worked).
Is there a solution to this, or is it simply not possible in C++?
No, the qualified class name must appear on any class member defined outside the class definition. (And there can only be one class definition, which is normally in a header file.)
The C++ Standard spells out this rule in [class.mfct]/4:
If the definition of a member function is lexically outside its class definition, the member function name shall be qualified by its class name using the :: operator.
and similarly in [class.static.data]/2 for static data members.
You might abbreviate this qualification using preprocessor macros, but that would seriously harm legibility and is not a common practice.
There is no idiomatic way to avoid this. Even if you or someone else might come up with a "hack" (macro-based, for example), it would make the code less readable for everyone. The normal and expected way to write C++ is for the member functions to have the preceding MyClass:: when defined outside the class definition.
I would suggest to look for a tool that can update signatures between header and source file on command.
Or, as the comments suggest, provide the definitions of your functions right with the declaration inside the class definition (i.e. provide inline definitions). But that has its own disadvantages.
Using C++20 modules, you can implement a class in one file:
module myproject.mymodule;
namespace mynamespace {
export struct my_class {
auto my_method() -> int {
return 8;
}
};
}
Or export a whole namespace fragment:
export namespace mynamespace {
struct my_class {
auto my_method() -> int {
return 8;
}
};
auto also_exported() -> void {
// ...
}
}
Then, instead of including it, you can import that module:
import myproject.mymodule;
auto frob() -> void {
auto my_instance = mynamespace::my_class{};
}
I usually declare in header file and implement in cpp file, but now I am doing an assignment, and, apparently for brevity, the instructor doesn't want me to do that, but insists that I write all the code in header files.
So, what is the best way to do that?
For classes, should I declare everything first, and then go to the bottom of the page and start implementing?
class myClass
{
void myMethod();
}
void myClass::myMethod() { //.... }
or should I just implement as I declare
class myClass
{
void myMethod() { //... } ;
}
What about free functions?
And when should I write "inline"?
or should I just implement as I declare
Yes, implement them in class, not out of class. When the (questionable) reasoning of your instructor for putting everything into a header refers to brevity, this is obviously the way to go.
What about free functions?
Same as with member functions, define them on the go.
And when should I write "inline"?
You should add inline to all ordinary free functions. It's unnecessary for function templates or in-class member function definitions. When you can use C++17, consider inline variables, too.
When declaring and implementing a class or struct in c++ we generally do:
H file
namespace Space{
class Something{
void method();
}
}
CPP file
void Space::Something::method(){
//do stuff
}
OR
namespace Space{
void Something::method(){
//do stuff
}
}
Note how it is possible to wrap all the implementations inside the namespace block so we don't need to write Space:: before each member.
Is there a way to wrap class members in some similar way?
Please note I want to keep source and header file separated. That's generally a good practice.
Not without sacrificing the separation between header and implementation (cpp) file.
You can declare everything inline in the header inside the class, but it's very messy for large classes.
What's the problem you're actually trying to solve? Or is it just typing time? :)
Yes:
.h file:
namespace Space{
class Something{
void method()
{
// do stuff
}
};
}
I don't recommend it, though.
You can not if you keep the .cpp file.
Otherwise, you can, but you would essentially just be dropping the .cpp file.
In your .h file, you could have:
namespace Space{
class Something{
void method()
{
//Method Logic
}
};
}
Except, as you know, there would be limitations as to where you could include the header.
I'm not so sure this will help you, the OP, as you seem to know what you're doing, but I'll include it for future users of the question:
What should go into an .h file?
No, unless you put the class members directly into the class definition
class Something
{
void method() {}
};
This is discouraged as it leads to header bloat if your class definition is in a header file.
I prefer not to use the wrapping method myself, so each function body explicitly states its namespace. This helps detect typos or dead code if you remove the prototype.
Is there any way in which to simplify the explicit statement of the class when implementing methods in the cpp file that was previously contracted in the h file?
Something like...
MyClass:: {
void my_method() { implementation };
void my_other() { implementation };
}
There isn't, but a good IDE will offer some Refactoring facilities to ease the typing. For Visual Studio, VisualAssist is a good plugin (not affiliated in any way).
You could optionally create your own macro, something like:
// This is very ungly, probably best avoided
#define lessTyping(method) MyClass::##method()
lessTyping(my_method)
{
}
But it would really hurt readbility.
No.
C++11 standard §9.3 [class.mfct] p5:
If the definition of a member function is lexically outside its class definition, the member function name shall be qualified by its class name using the :: operator.
No, the only way to avoid them is to use inline declaration directly in header file like in
class MyClass
{
void my_method() { implementation };
...
}
I am using an API that has a lot of functions in a class named TCODConsole as static functions. Now I thought that it was in a namespace, so I wrote: using namespace TCODConsole;. Then I found out that TCODConsole ain't a namespace, but a class.
Is there a way to import those functions in a similar way as you would use using namespace?
No, there is no shortcut way to call myStaticFun() instead of MyClass::myStaticFun(). You cannot do that with class. It's a class, not a namespace. But you can write something like a wrapper. That is you will add functions with same name and call the static methods from that functions. Something like this:
class MyClass {
static void fun();
};
void fun() {
MyClass::fun();
}
// call it
fun();
Not a very good way. Personally I think it is better to stick with the class instead of doing this.
Though I may misunderstand the question,
if shortening the qualification is the objective,
does typedefing like the following meet the purpose?
struct TCODConsole {
static void f();
static void g();
};
int main() {
typedef TCODConsole T;
T::f();
T::g();
}
Alternatively, if the class TCODConsole can be instantiated,
since static member function can be called with the same form as
non-static member function, the following code might meet the purpose:
int main() {
TCODConsole t;
t.f();
t.g();
}
I can't think of a clean way to do it, but I can think of a kinda ugly hack that will work, as long as the code using it is part of a class (and if TCODConsole really contains only static member functions). Let's say you are bar(), a member function of the class Foo, and you want to call a function baz() which is a static member of TCODConsole without fully-qualifying it. What you can do is to privately derive Foo from TCODConsole:
class Foo : private TCODConsole
{
void bar()
{
baz();
}
};
Yeah, that's ugly. :(
If you want to use Boost.PP (the Boost Preprocessor macro library - you don't need to compile or include anything else from Boost to use it), you can probably make a less ugly but quite a bit more convoluted macro which will "import" these functions for you, by wrapping them with inline functions inside another namespace (which you can then import at will). It would still require you to explicitly specify the name each of the functions you want to "import", so your code (minus the macro) will look something like this:
namespace TCODStatic
{
IMPORT_FROM_TCOD(foo)
IMPORT_FROM_TCOD(bar)
IMPORT_FROM_TCOD(baz)
IMPORT_FROM_TCOD(spaz)
}
and then you'll be able to write using namespace TCODStatic; anywhere you want.
Short answer: not without using macros. There is no mechanism in the C++ language proper to do something like this:
class A
{
public:
static void foo();
};
// ...
using A;
foo();
You could use a macro to build these expressions for you:
#define FOO() (A::foo())
FOO();
I would discourage this however, because it can become a maintennence nightmare is you make extensive use of such macros. You end up with code like this:
FOO();
BAR();
SUPERGIZMO(a, b, c);
...where none of these things are defined as first-class names anywhere in the program. You've lost all type checking, the code uses a "secret language" that only you know, and it becomes difficult to debug, extend and fix.
EDIT:
You could write a kind of bridge. Like this:
class FooBar
{
public:
static void gizmo();
};
namespace Foo
{
void gizmo() { FooBar::gizmo(); };
};
using namespace Foo;
gizmo();