C++ 如何做到这一点?

C++ 如何做到这一点?,c++,puzzle,C++,Puzzle,简化:因为之前提出问题的方式具有误导性。我的错误。也不要让人们的时间完全浪费 Y.h #ifndef Y_H #define Y_H #include <iostream> class X; class Y { private: friend class X; void Print() { std::cout << "Y::Print" << std::endl;

简化:因为之前提出问题的方式具有误导性。我的错误。也不要让人们的时间完全浪费

Y.h

#ifndef Y_H
#define Y_H

#include <iostream>

class X;
class Y
{
    private:
        friend class X;
        void Print()
        {
            std::cout << "Y::Print" << std::endl;
        }
};

#endif
#ifndef X_H
#define X_H

#include "Y.h"

class X
{
    public:
        void Something(Y* pY)
        {
            pY->Print();
        }
};          

#endif
这与我原来的问题有些不同。我为所有的麻烦道歉:)。我向你保证,这是可能的

规则: 不要改变Y.h或X.h。 让
X::Something
做一些它现在正在做的事情以外的事情


当我想到这一点时,我想到了这一点,如果可能的话,我更愿意获取并编辑定义
类节点的源代码,使
评估
虚拟,然后重新编译所需的一切。当然,这根本不是黑客行为


如果源代码不可用或者构建它的库将是一个巨大的痛苦,我可能(在Linux上)尝试使用
LD_PRELOAD
共享对象,该对象只包含(损坏的)符号
Node::Evaluate()

,如果可能并且不是一个巨大的痛苦,我更愿意获取并编辑定义
类节点的源代码,使
评估
虚拟化,然后重新编译所需的所有内容。当然,这根本不是黑客行为


如果源代码不可用,或者构建其库将是一个巨大的难题,我可能(在Linux上)尝试使用
LD_PRELOAD
共享对象,该对象只包含(损坏的)符号
Node::Evaluate()

没有通用的解决方案,因为Evaluate很可能已内联到Execute中。

没有可概括的解决方案,因为Evaluate很可能已内联到Execute中。

有一个类,比如说
MyNode
派生自
Node
类。为节点和新的
MyNode
类提供一个私有虚拟方法,比如
EvaluateImpl()
。修改
节点::Evaluate()
方法以调用新的私有虚拟方法
EvaluateImpl()
。将
Node::Evaluate()
的现有功能移动到新的
Node::EvaluateImpl()
方法。将新功能放入
MyNode::EvaluateImpl()

然后将派生类对象传递给
Parser::Execute()
方法

class Node
{
     private:
         friend class Parser;
         void Evaluate() { EvaluateImpl(); }
         virtual void EvaluateImpl(); //Move functionality  from Evaluate() to here
};

class MyNode
{
     private:
         virtual void EvaluateImpl(); //Implement your new functionality.
};

让一个类说
MyNode
派生自
Node
类。为节点和新的
MyNode
类提供一个私有虚拟方法,比如
EvaluateImpl()
。修改
节点::Evaluate()
方法以调用新的私有虚拟方法
EvaluateImpl()
。将
Node::Evaluate()
的现有功能移动到新的
Node::EvaluateImpl()
方法。将新功能放入
MyNode::EvaluateImpl()

然后将派生类对象传递给
Parser::Execute()
方法

class Node
{
     private:
         friend class Parser;
         void Evaluate() { EvaluateImpl(); }
         virtual void EvaluateImpl(); //Move functionality  from Evaluate() to here
};

class MyNode
{
     private:
         virtual void EvaluateImpl(); //Implement your new functionality.
};

如果可以修改解析器,请创建一个新函数EvaluateNode并将新方法放在其中

您必须用EvaluateNode替换所有要求值的调用。如果您依靠调用在无法修改的代码中求值,那么这将不起作用

另一种方法是创建另一个节点类,比如ModifiableNode,它有一个私有节点,通过调用节点方法(Evaluate方法除外)实现它的所有功能。然后在解析器中用ModifiableNode替换节点


如果您不能修改解析器,那么您必须按照aschepler的建议创建一个新函数,然后以某种方式诱使链接器提供您的函数而不是库的函数。我不知道该怎么做,对我来说这听起来真的是个坏主意。

如果你能修改解析器,创建一个新的函数EvaluateNode并将你的新方法放在那里

您必须用EvaluateNode替换所有要求值的调用。如果您依靠调用在无法修改的代码中求值,那么这将不起作用

另一种方法是创建另一个节点类,比如ModifiableNode,它有一个私有节点,通过调用节点方法(Evaluate方法除外)实现它的所有功能。然后在解析器中用ModifiableNode替换节点

如果您不能修改解析器,那么您必须按照aschepler的建议创建一个新函数,然后以某种方式诱使链接器提供您的函数而不是库的函数。我不知道该怎么做,对我来说这听起来真是个坏主意。

这是不可能的

在这一点上:

pRoot->Evaluate();
编译器已经知道它将调用
节点::Evaluate
,因为它是非虚拟的。您已经说过无法编辑此实现,因此现在您知道了唯一的方法是修改
Node::Evaluate
的实现

你说你也做不到。就这样,你不能


我建议你不要拐弯抹角,问一个真正的问题。说“这是我正在使用的库,这是我如何使用它,这是正在发生的事情,但这是我想要发生的事情。如何?”或者甚至将范围扩大到“这是我正在解决的问题,并解决它…”,以允许完全不同的方法

但用定义不清的参数和目标问这些“难题”问题是愚蠢的。所以不要这样做。

这是不可能的

在这一点上:

pRoot->Evaluate();
编译器已经知道它将调用
节点::Evaluate
,因为它是非虚拟的。您已经说过无法编辑此实现,因此现在您知道了唯一的方法是修改
Node::Evaluate
的实现

你说你也做不到。就这样,你不能


我建议你不要拐弯抹角,问一个真正的问题。说“这是我正在使用的库,这是我如何使用它,这是正在发生的事情,但这是我想要发生的事情。如何?”或者甚至将范围扩大到“这是我正在解决的问题,并解决它…”,以允许完全不同的方法


但用定义不清的参数和目标问这些“难题”问题是愚蠢的。所以不要。找到求值函数a的地址
#include "Y.h"
class Hack {
public:
  static void Print();
};

#define Y Hack
#include "X.h"
#undef Y

void Hack::Print() {
  std::cout << "Something else" << std::endl;
}

int main() {
  Hack y;
  X().Something(&y);
  return 0;
}