2

假设我有纯抽象类IHandler和派生自它的类:

class IHandler
{
public:
   virtual int process_input(char input) = 0;
};

class MyEngine : protected IHandler
{
public:
   virtual int process_input(char input) { /* implementation */ } 
};

我想在我的 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

这可以通过受保护的继承和隐式转换来完成吗?我只设法得到:

从“MyEngine *”到“IHandler *”的转换存在,但无法访问

由于我来自 C# 背景,这基本上是 C# 中的显式接口实现。这是 C++ 中的有效方法吗?

额外的:

为了更好地了解我为什么要这样做,请考虑以下几点:

TcpConnection通过 TCP 实现通信,并且在其构造函数中需要指向 interface 的指针ITcpEventHandler。当TcpConnection在套接字上获取一些数据时,它将该数据传递给它的ITcpEventHandlerusing ITcpEventHandler::incomingData,或者当它轮询它使用的传出数据时ITcpEventHandler::getOutgoingData

我的类HttpClient使用TcpConnection(聚合)并将自身传递给TcpConnection构造函数,并在这些接口方法中进行处理。

所以TcpConnection必须实现这些方法,但我不希望用户使用HttpClient直接访问ITcpEventHandler方法(incomingDatagetOutgoingData)。他们应该不能打电话incomingDatagetOutgoingData直接打电话。

希望这能澄清我的用例。

4

3 回答 3

6

派生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
};

在这里,在派生类中,您基本上覆盖了process_input函数的可见性,因此客户端只能通过指针或对基类的引用来调用它们。

这样,您将无法做到这一点:

MyEngine* ptr = new MyEngine();
ptr->process_input('a');   // ERROR!
std::cout << ptr->name();  // ERROR!

但这将是可能的:

IHandler* ptr = new MyEngine();
ptr->process_input('a');   // OK
std::cout << ptr->name();  // OK
于 2013-03-22T13:09:02.407 回答
1

在 C++protectedprivate继承服务中使用继承的实现。也就是说,你定义了一个带有方法的类,例如一个模板类,当你想使用它的功能而不是它的接口时,你继承protectedor private。所以实际上你的基类需要定义你想在子类中使用的方法。

是有关此主题的链接。这真的很难,我同意。

于 2013-03-22T13:08:10.043 回答
1

有点难以理解您希望在这里实现的真正目标,因为无论您在父级或子级上调用该方法,只要它是虚拟的,都会调用相同的方法。

那就是说你有几个选择。

您可以通过强制执行返回接口的创建调用来使用户无法获得子类型的指针(或对象)。那你就不用担心人为的限制了,他们根本就生不了孩子:

class Concrete : public Interface
{
public:
    static Interface* create() { return new Concrete; }

private:
    Concrete() { }
};

您可以覆盖界面,protected如另一个答案所示。

您可以利用非虚拟接口模式来制作父级中定义的整个可访问公共接口。然后不管他们有什么对象,他们总是从接口类中获取公共 API:

class Interface
{
public:
    void foo() { foo_impl(); }

private:
    virtual void foo_impl() = 0;
};

class Concrete
{
private:
    virtual void foo_impl() { }
};
于 2013-03-22T15:18:24.437 回答