从类外部访问专用虚拟函数

Accessing a private virtual function from outside the class

本文关键字:虚拟 函数 专用 访问 外部      更新时间:2023-10-16

我知道,就良好的编程实践而言,这是一个坏主意,但我一直在努力解决一个相对困难的问题,并希望获得一些见解。本质上,我试图输出一个类的所有成员如下:

class protoCalc
{
    private:
        int x; 
        int y;
        virtual int basicAddition()
        {
            return x + y;
        }
        virtual int basicMultiplication()
        {
           return x*y;
        }
public:
    protoCalc(){
        x = 14;
        y = 120;
    }
};

事实证明,访问x和y足够容易;为此,我写了一个函数(包括我对这是如何工作的想法,无论它们是否正确):

int private_member_Print(void* proto)
{
    protoCalc* medium = (protoCalc*)proto;
    protoCalc halfway = *medium;
    int* ptr = ((int *)(&halfway));
return ptr[1];

}

上面将返回x的值,如果使用ptr[2],它将返回y的值。

现在我有两个问题,第一个问题是ptr[0]指向什么?这部分内存难道不应该被私人成员x占用吗?因为它是protoCalc类的第一个成员?如果没有,那么这个地址是什么?

第二,如何访问虚拟功能?我的第一个直觉是地址ptr[3]将被basicAddition()虚拟函数和ptr[4]basicMultiplication()函数占用,但事实并非如此。当这不成立时,我的下一个想法是ptr[0]包含指向虚拟成员表位置的指针,该表包含我正在寻找的两个函数。然而,这也被证明是错误的。

那么,当我访问了私有成员x和y时,我如何在类之外访问这些虚拟函数呢?显然,我可以改变环境,让事情变得更容易,但这会破坏问题的目的。

您当前所做的是未定义的行为。在大多数情况下,对象在内存中的布局由编译器决定,并且您不知道编译器将把每个成员放在内存的何处。

话虽如此,实现这一点的方法是大量滥用模板。我强烈建议不要这样做,而是提供成员功能来访问所需的数据。

这是一个实际操作的例子。

#include <iostream>
class Priv {
private:
    int i;
    void print( ) {
        std::cout << i << std::endl;
    }
public:
    Priv( ) : i( 100 ) {}
    void print_pub( ) {
        std::cout << "Public" << std::endl;
        this->print( );
    }
};
template<typename Tag>
struct result {
  /* export it ... */
  typedef typename Tag::type type;
  static type ptr;
};
template<typename Tag>
typename result<Tag>::type result<Tag>::ptr;
template<typename Tag, typename Tag::type p>
struct rob : result<Tag> {
  /* fill it ... */
  struct filler {
    filler() { result<Tag>::ptr = p; }
  };
  static filler filler_obj;
};
template<typename Tag, typename Tag::type p>
typename rob<Tag, p>::filler rob<Tag, p>::filler_obj;
struct Priv_f { typedef void ( Priv::*type )(); };
template class rob< Priv_f, &Priv::print >;
struct Priv_i { typedef int Priv::*type; };
template class rob< Priv_i, &Priv::i >;
int main( ) {
    Priv p;
    (p.*result<Priv_i>::ptr) = 1;
    (p.*result<Priv_f>::ptr)(); 
}

rob/result模板类的解释可以在这里找到。它应该跨编译器工作。