3

in C# I created a static class which had a number of mathematical helper functions I could call directly without creating an instance of the class. I cannot seem to get this to work in C++.

For example, if the class is called MathsClass and has a function called MultiplyByThree then I would use it like this:

float Variable1 = MathsClass.MultiplyByThree(Variable1);

In the C++ version of my code I am getting the errors:

 'MathsClass' : illegal use of this type as an expression

and

 error C2228: left of '.MultiplyByThree' must have class/struct/union

How would I write the C++ equivalent of the C# static class to give this kind of functionality?

Dollarslice
  • 9,917
  • 22
  • 59
  • 87

6 Answers6

10

The easy answer is to use the :: operator instead of the . operator:

float Variable1 = MathsClass::MultiplyByThree(Variable1); 

But in C++, free functions are generally preferred over static class functions, unless you have a specific reason to put them in a class. For keeping them together, and not polluting the global namespace, you can put them in their own namespace:

In Math.h

namespace Math
{
    float MultiplyByThree(float x);
}

In Math.cpp:

#include "math.h"

namespace Math
{
    float MultiplyByThree(float x)
    {
        return x * 3;
    }
}

And to use it:

#include "math.h"

float Variable1 = Math::MultiplyByThree(Variable1); 

Even better, make it a template and the same code will work for floats, doubles, ints, complex, or any type that has operator* defined:

In Math.h

namespace Math
{
    template <typename T>
    T MultiplyByThree(T x)
    {
        return x * 3;
    }
}

The only issue being that you can't separate the definition into math.cpp, it has to be in the header.

Eclipse
  • 44,851
  • 20
  • 112
  • 171
  • just out of interest, how come you use the std namespace by writing using namespace std, but if you write your own namespace you do an #include? are they both interchangeable? – Dollarslice Nov 09 '11 at 16:03
  • 1
    `using` and `#include`s are unrelated. `#include` will inject whatever file is specified directly into the location of the `#include`. You can even `#include` something other than a header, though I've never yet encountered such a need. You need the include to get the declaration. You *can* but *do not need* to use the `using` and `using namespace` directive to avoid the need to scope into the namespace to access a member. The `std` namespace is very large and its members are declared/defined in many different headers. Thus, there is no "std.h" to include, but an `std` namespace. – Sion Sheevok Nov 09 '11 at 16:43
4

Use :: in place of .:

float Variable1 = MathsClass::MultiplyByThree(Variable1);

Also, make sure MultiplyByThree is declared static:

class MathsClass {
...

public:
  static float MultiplyByThree(float arg);

...
}

Lastly, if the class consists entirely of static helper functions, you might want to prohibit the creation of instances of MathsClass by making its constructor private.

NPE
  • 486,780
  • 108
  • 951
  • 1,012
2

The . operator only works on objects. The :: operator (Scope Resolution Operator) is used to access the members of a scope, in the sense of a namespace or type. The exact equivalent is like so:

class MathsClass
{
    static float MultiplyByThree(const float Value);
};

Calling it like so:

float TwoTimesThree = MathsClass::MultiplyByThree(2.0f);

I would not advise this however. Use a namespace instead. Does it make sense to allow the user to make a MathsClass object? If not, then simply make it a namespace. The syntax for calling the function remains the same.

namespace Maths
{
    float MultiplyByThree(const float Value);
}

float TwoTimesThree = Maths::MultiplyByThree(2.0f);

You can define Maths::MultiplyByThree in the header if you want it inlined (or attempt to inline it), but otherwise, you should define it separately in a ".CPP" file. In the ".CPP" file, you can either define it like this:

namespace Maths
{
    float MultiplyByThree(const float Value)
    {
        // Definition here.
    }
}

... or like this:

float Maths::MultiplyByThree(const float Value)
{
    // Definition here.
}
Sion Sheevok
  • 4,057
  • 2
  • 21
  • 37
  • I'd also like to mention [this answer](http://stackoverflow.com/questions/1434937/namespace-functions-versus-static-methods-on-a-class/1435105#1435105) in a vaguely related thread. – Sion Sheevok Nov 09 '11 at 16:01
1

Assuming that MultiplyByThree is a static method, you should call it as:

float var1 = MathsClass::MultiplyByThree(varx);

Wayne Tanner
  • 1,346
  • 11
  • 18
1

Usually, standalone functions will go in a namespace rather than a class:

namespace Maths {
    template <typename T> T MultiplyByThree(T const & x) {return x * 3;}
}

You then use the scope-resolution operator to access the function: Maths::MultiplyByThree

If for some reason you really want to make it a static member of a class, then the syntax is the same: static members can be accessed as either class_name::member or object.member, but not as class_name.member.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
0

Make all members of your class static and call them with the :: syntax.

The purpose of a C# static class is to prevent instantiation, so you should also make your MathsClass() constructor in the private section of your interface to prevent instantiation from ever occurring :)

John Humphreys
  • 37,047
  • 37
  • 155
  • 255