Reputation: 14423
Simplified: Because the way the problem was presented before was misleading. My mistake. Also not to make peoples' time a complete waste :) :::
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
X.h
#ifndef X_H
#define X_H
#include "Y.h"
class X
{
public:
void Something(Y* pY)
{
pY->Print();
}
};
#endif
This is somewhat different from my original problem. I apologize for all the trouble :). I assure you, this IS possible.
Rules:
Don't change Y.h or X.h.
Get X::Something
to do something other than what it is doing now.
This came to me when I was thinking about this.
Upvotes: 1
Views: 189
Reputation: 72473
Rules: Don't change Y.h or X.h. Get X::Something to do something other than what it is doing now.
Okay.
#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;
}
Of course, this won't change the behavior of any existing translation units which already use Something
, because you can't.
Also, if you try the same thing without the static
keyword, make sure classes Hack
and Y
are layout-compatible.
Upvotes: 1
Reputation: 147036
Easy. Never include X.h (your problem never specifies that it should be included in any translation units) and redefine class X inside another header. Problemo solvo.
Edit: You could also do something REALLY evil like
#define void virtual void
#include "X.h"
and then inherit, or
#define X X_impl
and write your own new X class.
Upvotes: 1
Reputation: 40897
Find the address of the evaluate function and rewrite the first instruction in it with a JMP to your own, which evaluates the implementation defined representation of Node.
Upvotes: 1
Reputation: 504303
It's impossible.
At this point:
pRoot->Evaluate();
The compiler already knows it'll be calling Node::Evaluate
, because it's non-virtual. You've said you cannot edit this implementation, so now you know the only path to take is to modify the implementation of Node::Evaluate
.
Which you said you also cannot do. So that's it, you can't.
I'd recommend you stop beating around the bush and ask a real question. Say "this is the library I'm using, this is how I'm using it, here's what's happening, but here's what I want to happen. How?" Or even expand the scope to "Here's the problem I'm solving, and to solve it..." to allow completely different approaches.
But asking these "puzzle" questions with ill-defined parameters and goals is silly. So don't.
Upvotes: 3
Reputation: 2520
If you can modify the parser make a new function EvaluateNode and put your new method in there.
You will have to replace all calls to Evaluate with EvaluateNode. This wouldn't work if you are relying on calls to Evaluate in code you can't modify.
Another way is to create another node class, say ModifiableNode which has a private node and implements all of it's functionality by calling Node methods, except for the Evaluate method. Then replace Node with ModifiableNode in Parser.
If you can't modify Parser, then you'll have to do something like aschepler suggested and create a new function and then somehow trick the linker into supplying your function instead of the library's. I have no idea how to do this, and sounds like a really bad idea to me.
Upvotes: 0
Reputation: 687
Have a class say MyNode
derive from Node
class. Provide a private virtual method say EvaluateImpl()
to Node and to the new MyNode
classes. Modify the Node::Evaluate()
method to call the new private virtual method EvaluateImpl()
. Move the existing functionality of Node::Evaluate()
to the new Node::EvaluateImpl()
method. Put your new functionality to MyNode::EvaluateImpl()
Then pass the derived class object to Parser::Execute()
method.
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.
};
Upvotes: 0
Reputation: 42932
There's no generalizable solution, because Evaluate may well have been inlined into Execute.
Upvotes: 1
Reputation: 72473
If possible and not a huge pain, I would prefer to get and edit the source which defines class Node
, make Evaluate
virtual, and then recompile everything needed. Of course, this is not a hack at all.
If the source code is not available or building its library would be a huge pain, I might (on Linux) attempt using an LD_PRELOAD
shared object containing only the (mangled) symbol Node::Evaluate()
.
Upvotes: 1