omi*_*nes 2 c++ inheritance abstract-class casting explicit-implementation
假设我有纯抽象类IHandler和我的类派生于它:
class IHandler
{
public:
virtual int process_input(char input) = 0;
};
class MyEngine : protected IHandler
{
public:
virtual int process_input(char input) { /* implementation */ }
};
Run Code Online (Sandbox Code Playgroud)
我希望在我的MyEngine中继承该类,以便我可以传递MyEngine*给任何期望的人,IHandler*并让他们能够使用process_input.但是我不想允许访问,MyEngine*因为我不想公开实现细节.
MyEngine* ptr = new MyEngine();
ptr->process_input('a'); //NOT POSSIBLE
static_cast<IHandler*>(ptr)->process_input('a'); //OK
IHandler* ptr2 = ptr; //OK
ptr2->process_input('a'); //OK
Run Code Online (Sandbox Code Playgroud)
这可以通过受保护的继承和隐式转换来完成吗?我只是设法得到:
从"MyEngine*"到"IHandler*"的转换存在,但无法访问
由于我来自C#后台,这基本上是C#中的显式接口实现.这是C++中的有效方法吗?
额外:
为了更好地了解我为什么要这样做,请考虑以下事项:
类TcpConnection通过TCP实现通信,并且在其构造函数中需要指向接口的指针ITcpEventHandler.当TcpConnection在套接字上获取某些数据时,它会将该数据传递给它ITcpEventHandler使用ITcpEventHandler::incomingData,或者当它轮询它使用的传出数据时ITcpEventHandler::getOutgoingData.
我的类HttpClient使用TcpConnection(聚合)并将自身传递给TcpConnection构造函数,并在这些接口方法中进行处理.
所以TcpConnection必须实现这些方法,但我不希望用户使用HttpClient直接访问ITcpEventHandler方法(incomingData,getOutgoingData).他们不应该打电话incomingData或getOutgoingData直接打电话.
希望这能澄清我的用例.
派生protected使得通过指向派生类的指针无法访问基类的成员,并且不允许隐式转换.
在我看来,你想要的不是禁止通过基类(接口)访问,而是通过派生类(具体实现):
class IHandler
{
public:
virtual int process_input(char input) = 0; //pure virtual
virtual std::string name() { return "IHandler"; } //simple implementation
};
class MyEngine : public IHandler
// ^^^^^^
{
protected: // <== Make the functions inaccessible from a pointer
// or reference to `MyEngine`.
virtual int process_input(char input) { return 0; } //override pure virtual
using IHandler::name; //use IHandler version
};
Run Code Online (Sandbox Code Playgroud)
在这里,在派生类中,您基本上覆盖了process_input函数的可见性,因此客户端只能通过指针或对基类的引用来调用它们.
这样你就不可能做到这一点:
MyEngine* ptr = new MyEngine();
ptr->process_input('a'); // ERROR!
std::cout << ptr->name(); // ERROR!
Run Code Online (Sandbox Code Playgroud)
但这将是可能的:
IHandler* ptr = new MyEngine();
ptr->process_input('a'); // OK
std::cout << ptr->name(); // OK
Run Code Online (Sandbox Code Playgroud)