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.
Related
I find it a very appealing programming style define all the methods of a struct/class directly inline in the struct, eg only define structs this way:
"A.hpp"
class A;
"A.cpp"
class A
{
A() = default;
void method() { }
};
rather than
"A.hpp"
class A
{
A();
void method();
};
"A.cpp"
A::A() = default;
void A::method() { }
This means putting classes/struct definitions in a code file and only including declaration in header files.
However, this runs into the problems when the compiler would need to know the struct/class layout in other code files.
Is there a programming style that supports this? Perhaps only getting and setting fields through getters/setters? This way would however lead to large amounts of boilerplate.
Just including the struct/class definition in the header file leads to issues with mutually recursive header files, unless one explicitly puts the declarations in another.
I can achieve this programming style in a language like D with a module system, but how does one achieve it in C++?
What are you doing is called forward declaration.
You will be not able to do anything (f.e. call methods, create instances) with this class in all other translation units, except one .cpp file, where you define it. So, this idea is completely useless and bad. And you will get a boatload of linker errors.
So, you need to either stick to style #2. Or define inline methods in header file, like this
struct A {
A() {} // something
int func() { /* function body */
}
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.
I have a class:
class M {
public:
static std::string t[];
};
with an initialization that comes later. I want to use the M::t later in a different class (header file):
class Use {
public:
void f() { std::cout << M::t[0] << std::endl; }
};
Is there any way to achieve this without including the whole class M for the header file of the Use? I understand that forward declarations do not allow accessing class members, however this beauty is a static one, so it shouldn't be a huge problem for the compiler..
No, you can't. You can either include the header in the header, or separate the implementation Use::f in an implementation file and include M's header there.
There are no partial classes like in C#, where you can define a class in several files.
Since you are making it a public static member, why don't you create a namespace and embed it there?
namespace myns{
std::string t[];
}
You can access it from anywhere then, just like you would have done with a public static class member.
Forward declarations only allow you to use forward-declared-class pointers or references, not members! If you want to use class members like in your example you have to include the class header, even if it's static.
Here is the solution if you don't want to include M.h in your Use.h header:
Use.h
class Use {
public:
void f();
};
Use.cpp
#include "M.h"
#include "Use.h"
void Use::f() {
std::cout << M::t[0] << std::endl;
}
Also, you have to know it's a bad habit to write code in header files, except of course for inline and templates.
In C++, what's the benefit of having a class with functions...
say
class someClass{
public:
void someFunc(int arg1);
};
then having the function's actual functionality declared after int main
int main()
{ return 0; }
void someClass::someFunc(int arg1)
{ cout<<arg1; }
Furthermore, what's the benefit of declaring the class in a .h header file, then putting the functionality in a .cpp file that #includes the .h file?
Dependency management. Users of the class only need to include the header file, so they don't depend on the implementation.
Another use is breaking circular dependencies.
Both issues may look like a waste of time with toy programs, but they start to grow into a really bad problem as the program grows.
I was wondering if there is a way to put objects of a class in a header?
For example:
class MyClass {
} object;
If I made an object there and then include the header in more than one source file, I get an error of multiply defined symbols found. I am new so don't understand fully everything.
Also, I want to do something like object.function() inside of a different function which is a member of a different class how can I do that?
Assuming you want a single object, in the header file just declare the object:
extern blabla object;
and then in one source file define it:
blabla object;
As for calling a method on an object from a different class, that is perfectly fine as long as the method is public.
class foo
{
public:
void public_method();
private:
void private_method();
};
void some_other_class::method(foo &f)
{
f.public_method(); // this is fine
f.private_method(); // this is not okay, private_method can only be called from
// within foo
}
There's also a third visibility (protected), which comes into play once you start dealing with inheritance.
You can find ways to do it (see the other answers), but just don't do it. As you said, you are new to C++, so better learn the good practices, and when you need global objects - create them in the source (cpp) file.
Besides it, try to avoid using global objects at all, and define your objects inside the classes or functions.
It's not a good practice to put definitions in header files as this would result to the error you encountered. Although there are ways to get around this (extern, header guard), it should be avoided as much as possible. Just remember, put declarations in header files, definitions in source files.
About your second question note you can also call a static method using the :: operator and the class name (without an instance) :
void AnOtherClass::method()
{
TheFirstClass::static_method();
}
You could also make a use of the singleton pattern, if that fits your need in this case.
For your second question. You can always make a class object as a (private) member variable of the class you want to call object.function() from.
For example:
// File a.h, includeguards etc. left out for clarity
class A {
public:
void func();
};
// File b.h
#include "a.h"
class B {
public:
void func();
private:
A object;
};
// File b.c
#include "b.h"
void B::func()
{
object.func();
}
Hope that helps.