Can you define C++ methods in a reopened class environment, rather than by prefixing with the class name?

Viewed 70

In every lesson and book on C++ I've ever seen, a class has been written like this:

header.h

class MyClass
{
   ...
   int myMethod(int my_para);
};

source.cpp

...
int
MyClass::myMethod(int my_para)
{
   ...
}

But I do find that the MyClass:: just adds to the natural chaos and bewilderment of C++, especially when MyClass is actually more like MySomethingSomethingCreator. I would like to write my class definitions in more of a namespace style, like this:

header.h

class MyClass
{
   ...
   int myMethod(int my_para);
};

source.cpp

class MyClass
{
   ...
   int myMethod(int my_para)
   {
      ...
   }
}

Now, I know from trying that doing exactly this does not work, but is there a way to do something similar - just to remove a little of the noise? I am not interested in defining functions actually inside the class declaration - that's the work of the devil!

3 Answers

but is there a way to do something similar

No.

MyClass:: just adds to the natural chaos and bewilderment of C++

It's just one of the little things that a new C++ programmer has to learn to accept. Once you get used to it, it will no longer be bewildering.

MyClass:: just adds to the natural chaos and bewilderment of C++

I wouldn't agree with you. Imagine you are working with a huge code database, and you come across a definition of a function in .cpp file like this.

.
.
.
.
    int myfunc(std::string some_arg)
    {
        //whatever can be here    
    }
.
.
.
.
.

And now you would wonder, is this a function in a namespace or method of some class. Of course the class specifier you suggested would appear above, but in can be thousand of lines above, or even 10 thousands, which one probably wouldn't want to deal with. Someone would like to know if it is a method or function by directly looking on it.

The MyClass:: specifier serves greatly for this purpose.

You cannot. This is generally not a problem, though. In fact, there is good reason to want to do this with free functions. John Lakos points out in Large-Scale C++ Volume I (2020) p. 155–156, you can (and may want to) do this:

// foo.h
namespace my_product {

int foo(int);

} // namespace my_product

then

// foo.cpp
#include <my_product/foo.h>

int my_product::foo(int x) {
    return x * 2;
}

The advantage of this is: suppose you want to change the signature to take float and you change it in the .cpp to float my_product::foo(float x). If done this way, float my_product::foo(float x) can only define the function, it can't declare it, so you'd get a compile error: https://godbolt.org/z/eGbv3rTx5

error: out-of-line definition of 'foo' does not match any declaration in namespace 'my_product'
float my_product::foo(float x) {
                  ^~~

whereas if your .cpp file is

// foo.cpp
#include <my_product/foo.h>

namespace my_product {

float foo(float x) {
    return x * 2;
}

} // namespace my_product

and you try to use the function, you have to wait for the whole project to build and then get a link error: https://godbolt.org/z/soo7r97fG

undefined reference to `my_product::foo(int)'

I've started to get in this habit of defining functions like this so I can have immediate compile errors rather than waiting for a potentially big build only to get a link error, which then requires fixing the header (hopefully correctly!) and then waiting again for a big rebuild.

Related