我在标题Foo
中定义了一个类foo.hpp
。
class Foo{
... some methods and properties ...
};
此外,我需要一个函数bar()
,它具有以下属性:
bar()
应在文件foo.cpp
中定义,其符号不得导出,我想使用内部链接,因为bar()
仅用于foo.cpp
bar()
可以访问函数Foo
的私有元素。bar()
不能是成员函数,因为我想将其地址传递给另一个使用它作为回调的函数。C ++中是否可以实现上述目标?
我尝试了以下操作:由于链接应该是内部的,我需要使用static
bar()
关键字bar()
。friend
。此外,Foo
需要在foo.hpp
中声明为bar()
Foo
,因为它可以访问其私人成员。在see for example here之后,我需要将foo.hpp
之前的声明为static void bar();
class Foo{
... some methods and properties ...
friend void bar();
};
静止的。所以我在foo.cpp
static void bar(){
... definition of bar()
}
然后foo.cpp
将包含代码
declared ‘static’ but never defined
然而,这有以下缺点:
在其他不涉及bar()
的编译单元中,我得到了一个
警告说foo.hpp
。
包含Foo
的任何代码都可以看到bar()
的声明。我不希望这样,因为可以通过在其他编译单元中重新定义bar()
来使用它来访问Foo
的私有成员。
所以这不起作用。你会如何解决这个问题?
注意:当然sort_values
实际上有一些参数用于访问In [135]: df['rank'] = df.sort_values(['col_a', 'col_b'])['col_b'].index + 1
In [136]: df
Out[136]:
col_a col_b rank
0 0 5 2
1 0 2 1
2 0 8 3
3 1 3 4
4 1 7 6
5 1 4 5
的特定实例。我在这里省略了它们。
答案 0 :(得分:3)
只需使bar
成为该类的静态成员函数。它使它成为一个全局函数,其名称作用于类(意味着您可以将其用作常规函数指针)。您甚至可以将其设为私有,因此只有您班级的成员可以调用它。
答案 1 :(得分:1)
这应该是你要找的东西:
<强> foo.h中强>
class Foo {
private:
int f;
public:
Foo() : f( 5 ) {}
int fOf() const {
return f;
}
void callModify();
private:
static friend void modifyFoo(Foo& F); // your bar
};
<强> Foo.cpp中强>
#include "Foo.h"
// your static bar() -- must be defined first
static void modifyFoo( Foo& F ) {
F.f *= 2;
}
void Foo::callModify() { // caller to your static bar
modifyFoo( *this ); // using it in your class
}
<强>的main.cpp 强>
#include <iostream>
#include "Foo.h"
int main() {
Foo foo;
std::cout << foo.fOf() << std::endl;
foo.callModify();
std::cout << foo.fOf() << std::endl;
std::cout << "\nPress any key and enter to quit.";
std::cin.get();
return 0;
}
如果您尝试调用Foo.cpp
之外的modifyFoo(),则不会声明也不会定义它,因为它是private static friend
Foo
。如果您希望它对世界其他地方可见,那么您可以在课程中将其设为public
。如果您正在使用继承和多态,那么您可以为所有子类创建protected
,同时保持它不受外部对象的影响。
编辑 - 根据OP想要的性质,我必须这样做:它涉及使用包含静态方法的内部公共结构。然后该类具有调用修饰符的调用方法,但它也将返回内部结构。此结构是其父类的朋友。
class Foo {
public:
struct Modifier {
friend class Foo;
static void modify( class Foo& f );
};
private:
Modifier modifier;
int f;
public:
Foo : f(5) {}
int fOf() const {
return f;
}
Foo::Modifier caller() {
modifier.modify( *this );
return this->modifier;
}
private:
static friend struct FooModifier;
static friend void Modifier::modifier( Foo& f );
};
#include "Foo.h";
void Foo::Modifier::modify( class Foo& f ) {
F.f *= 4;
}
#include <iostream>
#include "Foo.h"
int main() {
Foo foo;
std::cout << foo.fOf() << std::endl;
Foo::Modifier m = foo.caller();
std::cout << foo.fOf() << std::endl;
m.modifiy( foo );
std::cout << foo.fOf() << std::endl;
// you can now pass the struct instance of `m` to your
// library which conatiners the modifier function.
return 0;
}
输出
5
20
80
通过这种设置,您可以创建Foo::Modifier
的实例,因为它在Foo
的类中是公开的。它的内部方法是静态的,并引用Foo
的特定对象,它是Foo
的朋友。这样,您现在可以将Foo::Modifier
的对象m
作为struct
传递到您的库,或者您可以使用m.modify( "some relative object of Foo" );
传递函数地址
您要求的严格要求并非易事。
答案 2 :(得分:0)
我想要的似乎不可能。似乎唯一的选择如下:
bar()
中的函数foo.hpp
声明为朋友,只在foo.cpp
声明并将其定义为静态,并使用带有指针和强制转换的脏技巧来更改私有元素Foo
的实例。我不喜欢这个。bar()
对于包含foo.hpp
的代码不应显示的要求,并使用NathanOliver的答案。bar()
可以访问Foo
实例的私有成员的要求,并在foo.cpp
中使用匿名命名空间,我们在subFoo
中派生Foo
bar()
(不添加新成员)并将foo.hpp
定义为匿名命名空间中的友元函数,并且不在标题Foo
中声明它。如果我们在Foo
中将subFoo
的实例投射到bar()
,它就可以访问至少受保护的fputs(strstr(line, p_name), fp2);
成员。我将使用第三个选项。