C++ - 从类外部访问私有成员

4
我想知道是否有办法从类外访问私有成员。我来解释一下我的问题。
我有一个.hpp文件,其中包含类的定义以及其私有成员和公共函数(我只想导出公共函数)。在相应的.cpp文件中,我必须使用一些“支持”函数来访问.hpp中定义的类的私有成员。
以下是我代码的部分内容:
--- .hpp ---
namespace vision {
class CameraAcquisition {

    /* MEMBERS */
    CvSize size;
    CvCapture *device;
    CvScalar hsv_min,hsv_min2,hsv_max,hsv_max2;

    /* METHODS */

public:
    CameraAcquisition();
    ~CameraAcquisition();
    int findBall();
};
}

--- .cpp ---

#include "CameraAcquisition.hpp"

using namespace vision;

IplImage *grabFrame() {
     // code here
}

IplImage *convertToHSV(IplImage *origin) {
// code here
}

IplImage *calculateThresholdedImage(IplImage *converted) {
// code here
}

我需要的是这三个函数能够访问到 CameraAcquisition 类的成员变量。有什么办法可以实现吗?欢迎提出建议。谢谢大家。
编辑 很抱歉,我在这里忘记了一项重要信息。在源文件中,findBall() 必须调用这些方法。我定义这些方法是为了使代码更易读。我不能在类定义中声明这些方法,因为我不想导出它们。 如果我将它们声明在“private”块中,则一切正常,但可能并不正确(我不认为提供一个带有私有方法的头文件有意义)。

你能改变涉及的头文件吗?如果可以,并且两个类之间存在强耦合,则可以使用友元关系。请注意,友元关系在这种情况下增强了封装性,而不是像一些人所建议的那样破坏了它。这比破坏封装的getter、setter方法或使用宏进行危险的黑客行为要好得多。只需不要选择这些方法,编写可读性和可维护性的代码,而不是除了你以外没有人能够理解/维护的奇怪东西。 - Alok Save
可能是 使用模板技巧访问私有成员 的重复问题。 - bames53
5个回答

3
如果那些成员被设置为“私有”,而你需要访问它们,那么你正在做一些错误的事情,所以我的建议是不要这样做。
现在让我们认真对待这个问题-有一些方法-免责声明:并非所有方法都安全、可移植或保证有效: 1)预处理器滥用
#define class struct
#define private public
#include "CameraAcquisition.h"
#undef class
#undef private

2) 虚假类


class MyCameraAcquisition {
public: //<--- public in your class
    /* MEMBERS */
    CvSize size;
    CvCapture *device;
    CvScalar hsv_min,hsv_min2,hsv_max,hsv_max2;

    /* METHODS */

public:
    CameraAcquisition();
    ~CameraAcquisition();
    int findBall();
};

CameraAcquisition prvt;
MyCameraAcquisition publ = (MyCameraAcquisition&) prvt;

3) 模板滥用 由litb发布 - http://bloglitb.blogspot.com/2010/07/access-to-private-members-thats-easy.html

这篇文章实际上是遵循标准的,令人惊讶。


2

您不应该想要访问对象的私有成员。可以考虑提供公共 getter/setter 成员函数,以便外部代码可以使用它们来影响私有成员变量。

或者,您可以将支持函数作为类的成员,这样它就可以自动访问私有成员。

如果您真的想要访问私有成员,可以使用 friend 关键字将另一个类或函数声明为当前类的友元。

class A
{
  int a; // private
  friend class B;
  friend void f(A*);
};

在这里,类 B(即其成员函数)和自由函数 f 都可以访问 A::a

1
如果他能添加“好友”,我相信他可以将成员设为“公开”。 - Luchian Grigore
1
但是公开成员供所有人查看/更改和声明一些受信任的“朋友”之间确实存在差异。 - Attila
我知道有这个功能,但不太清楚他是否可以更改头文件。 - Luchian Grigore
我不想更改头文件,那是我想要导出的。我可以在私有代码块中声明这些函数,但是呈现一个带有“私有”函数的头文件似乎并不合适,因为最终用户甚至都不应该知道它们存在。 - paxilpaz
在类定义中拥有private成员是非常正常的。如果你想隐藏实际的实现,可以查找PIMPL习惯用法(Private IMPLementation——基本上,你有一个前向声明的结构体,其中包含所有私有实现细节,类持有指向该结构的(私有)指针;结构的实际定义在相应的实现.cpp文件中)。 - Attila

0

所使用的编译器是Visual Studio 2015。
这种方法不被推荐,但可行。
让我们考虑以下类

class mydata
{
    private:
    int x;
    public:
    mydata(int no)
    {
        x=no;
    }
}

类对象中仅存储数据成员。 现在我可以使用以下函数访问 x。 由于我知道 class mydata 仅有一个变量,它必须是 int x

int getx(mydata *d)
{
    return ((int*)d)[0];

    /*
    How did this work?
    -> d is pointing to the mydata object. 
    as I typecasted it to int* it will be considered as int array.
    Of that array (which has lenght 1) access the first element.
    */
}

如果有另一个变量,比如类型为“DATATYPE”的y
现在,要访问y,我们必须从对象的基础上计算它的偏移量。
通常,数据存储的顺序与声明的顺序相同。
此外,在类中存在异构数据类型的情况下,需要考虑结构填充。 我建议您深入阅读结构填充。
然后我们可以得到y。
myclass *ptr =new myclass();
int offset_y=//whatever offset of y in number of bytes from base of object of perticular class;
char *byte_ptr_y=((char*)ptr)[offset_y];
DATATYPE y=*((DATATYPE*)byte_ptr_y);

0
在你的CameraAcquisition类中使用getter方法
例如: CVSize getSize() { return size; } CvCapture* getDevice { return device; } 等等...

0

你可以通过在类定义中添加声明语句将它们声明为友元:

friend IplImage * ::grabFrame();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接