2015-04-01 79 views
3

我在file1.cpp的頭文件interface.h和一些靜態函數(foobar和幾個更多)中有一個類MyClass聲明。靜態函數僅用於file1.cpp之內,但它們需要修改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);   
} 

理念1:不知何故聲明它們爲MyClass朋友?

爲什麼它不好:它們是靜態的,在不同的編譯單元中。除此之外,他們會將他們暴露給MyClass的用戶,他們不需要知道任何關於他們的信息。

理念2:不要有想法2.

排序鏈接:Is it possible to declare a friend function as static?

+1

您是否考慮過重新設計您的班級以免它需要朋友?需要更多的上下文來建議。 – 2015-04-01 12:57:27

+0

在你的例子中,我會簡單地爲'someVal'編寫一個公共setter,並在'doSomething'中使用它。除非你想阻止任何人訪問setter,否則不需要朋友。正如尼爾所說,需要更多信息來決定。 – user463035818 2015-04-01 13:04:02

+0

'foo'和'bar'函數比示例更復雜(所以它們不能改爲簡單的setter和getters)關鍵是要有一些可以修改類的函數,但是它不會混淆它的接口。 – user10607 2015-04-01 13:11:37

回答

3

排序的鏈接:是否有可能聲明友元函數靜態?

我個人覺得整個事情friend有點打破封裝一個黑客攻擊,但你問了一個有效的問題,答案是,你可以達到你想要一個幫手類什麼:

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); 
} 

你真的確定要這樣做嗎?你確定你不想在MyClass中封裝MyClass的增變器嗎?

+0

我不是100%肯定的))但是大約有10個函數(大約10個mutators),所以我認爲如果我把它們作爲私有方法放在MyClass中,它們只會分散這個類的用戶。 **但** **也許它不是一個壞主意,只是將它們添加爲私有,因爲用戶不應該看私人成員。你明白我的意思嗎? – user10607 2015-04-01 13:51:47

0

聽起來很奇怪(而且看起來),你實際上可以閱讀&編寫類/結構的私有成員。

這並不漂亮,當然也不鼓勵,但可行。

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; 
} 

當我第一次看到它時,我也想過:HOLY S ***!

0
// 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 
+0

你是對的我雖然他在談論稍微不同的somethign。但是,你看,我只希望函數'foo'和'bar'能夠設置'someval'。在這個解決方案中,任何人都可以調用'SetSomeval()'對嗎? – user10607 2015-04-01 13:55:48

+0

哦,我明白了。那麼你可以創建與MyClass結緣的函數來處理設置。我將修改我之前添加的代碼,向您展示我所做的 – 2015-04-01 15:49:12