C++ 如何做到这一点?
简化:因为之前提出问题的方式具有误导性。我的错误。也不要让人们的时间完全浪费 Y.hC++ 如何做到这一点?,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;
#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;
}