user10607
user10607

Reputation: 3071

Declare static functions as friend function?

I have a class MyClass declaration in a header file interface.h and some static functions (foo and bar and a few more) in file1.cpp. The static functions are only used inside file1.cpp but they need to modify private/protected members of MyClass`.

// in "interface.h"
class MyClass {
// maybe declare as friend?
// friend static void foo(MyClass &ref);
private:
    double someval;
}

// in "file1.cpp"
static void foo(MyClass &ref) {
    ref.someval = 41.0;
}
static void bar(MyClass &ref) {
    ref.someval = 0.42;
}

// function that uses foo/bar
void doSomething(MyClass &ref) {
    foo(ref);           
}

Idea 1: Somehow declare them as friends of MyClass?

Why its not good: They are static AND are in a different compilation unit. Besides that would expose them to the user of MyClass who does not need to know anything about them.

Idea 2: Don't have idea 2.

Sort of linked: Is it possible to declare a friend function as static?

Upvotes: 3

Views: 2880

Answers (3)

Duly Kinsky
Duly Kinsky

Reputation: 996

// in "interface.h"
class MyClass {
  // maybe declare as friend?
  // friend static void foo(MyClass &ref);
public:

  friend class SetSomevalClass; // make the classes friends

private:

  double someval;
};

class SetSomevalClass // functor class(or function class)
{
public:
  double operator()(MyClass n, double data) // this could have been void
  {
    n.someval = data; //set somevalue to data
    return n.someval; //return somevalue
    // return is solely used to show result in foo() and bar()
  }
};


// in "file1.cpp"
static void foo(MyClass &ref)
{
  SetSomevalClass s; //create functor object

  //s(ref, 40);
  //this would be the end of the foo function(uncommented) if we did        not want to show the result

  std::cout << "foo()" << s(ref, 40) << std::endl;
  //simply to show result

}
static void bar(MyClass &ref)
{
  SetSomevalClass s;

  //s(ref,2);

  //this would be the end of the foo function(uncommented) if we did not want to show the result

  std::cout << "bar()" << s(ref, 2) << std::endl;
}

// function that uses foo/bar
void doSomething(MyClass &ref) //calls both foo() and bar()
{
  foo(ref);
  bar(ref);

}

int main()
{
  MyClass s;
  doSomething(s); 
}// end main

Upvotes: 0

Zilicon
Zilicon

Reputation: 3860

As weird as it may sound (and look), you can actually read & write private members of a class / struct.

It's not pretty, and certainly not encouraged, but doable.

template<typename T>
struct invisible
{
    static typename T::type value;
};

template<typename T>
typename T::type invisible<T>::value;

template<typename T, typename T::type P>
class construct_invisible
{
    construct_invisible(){ invisible<T>::value = P; }
    static const construct_invisible instance;
};

template<typename T, typename T::type P>
const construct_invisible<T, P> construct_invisible<T, P>::instance;

struct MyClass_someval{ typedef double MyClass::*type; };
template class construct_invisible<MyClass_someval, &MyClass::someval>;

static void foo(MyClass &ref) {
    ref.*invisible<MyClass_someval>::value = 41.0;
}

When I first saw it I also thought: HOLY S***!

Upvotes: 0

Andy Brown
Andy Brown

Reputation: 12999

Sort of linked: Is it possible to declare a friend function as static?

Personally I find the whole friend thing a bit of a hack that breaks encapsulation but you've asked a valid question and the answer is that you can achieve what you want with a helper class:

file1.h

class MyClass {
private:
  double someval;

  friend class MyClassHelper;
};

file1.cpp

#include "file1.h"


struct MyClassHelper {
  static void mutateMyClass(MyClass& ref) {
    ref.someval=42;
  }
};


// in "file1.cpp"
static void foo(MyClass &ref) {
  MyClassHelper::mutateMyClass(ref);
}

Are you really sure you want to do it like this? Are you sure you don't want to encapsulate MyClass's mutators inside MyClass itself?

Upvotes: 3

Related Questions