用 C++ 实现接口?

Posted

技术标签:

【中文标题】用 C++ 实现接口?【英文标题】:Implement an interface in C++? 【发布时间】:2013-01-06 19:56:58 【问题描述】:

我想实现我在 C++ 项目的引擎 (Unity3D) 中看到的行为。

以下代码是 C#(Unity 的语言):

using UnityEngine;
using System.Collections;

public class example : MonoBehaviour 

    void Update() 
        //Update is called every frame
    

由于我无法访问 MonoBehavior 源,我只能猜测 Update() 是一个可以像这样实现的虚函数。

我想在 C++ 中复制相同的行为。在main() 中有一个循环,一个超级对象将在该循环中调用它的Update() 方法,它的所有子对象都应该继承这个超级对象,并有可能实现Update() 并使用它。

我知道这是一个模棱两可的问题,但我到处寻找答案却没有找到答案。

这是一个例子:

class Base

 public:
     virtual void Update();
;

class Object: public Base

 public:
     void Update();
;

void main()

     Base* base;
     while(1)
     
        base->Update();
     

结果应该是应该通过Base调用Object的Update()。我是 100% 上面的代码不起作用,这就是为什么我需要一些想法。

【问题讨论】:

是的,它是模棱两可的。我无法理解。有没有更全面的例子? Unity 似乎对方法名称使用反射和约定来查找类实现的方法。我不确定您是否可以在 C++ 中复制它。你确定你想要这个,或者实际上是在问如何创建一个虚拟方法并在 C++ 中覆盖它? 我正在开发一个项目,其中包含许多需要 Update() 的对象以及它的完成方式,通过继承和虚拟化将更新深入到对象。我希望能够创建一种更通用的方法,比如 Unity,但我发现它相当复杂。 【参考方案1】:

C++ 没有接口。您使用纯虚方法创建一个抽象类。

class MonoBehaviour 

    virtual void Update() = 0;
;

class your_class : MonoBehaviour 

    void Update() 
     
        // implement here. 
    
;

【讨论】:

这不是 Unity 所做的。抽象类没有派生类覆盖的虚拟方法。它是实现方法的派生类,Unity使用反射来找到它。另一方面,您的答案可能是 OP 要求的答案;这个问题模棱两可。 C++ 不支持反射。 garret.ru/cppreflection/docs/reflect.html【参考方案2】:

可能存在子类方法和基类方法的签名不相同,即它们具有相同的名称但返回不同的东西或具有不同的参数。这是始终调用基类方法的一种方式。

或者你可能只是在主函数中构造基类对象而不是子类对象。在 main 函数中放置一个中断来检查您正在为其调用 Update 的对象的实际类型。

您发布的代码应该可以正常工作。基类是否是抽象的并不重要。为了便于实现子类,我更喜欢使其具体化并在应该为 = 0 的方法中抛出异常(我不必从一开始就实现完整的行为,只需要我关注的方法和我正在测试;所以它会逐步进行)。

是的,坚持公共继承。

编辑: 或者,如果您有这样的事情,可能会涉及到对象切片:

Derived* d_ptr = new Derived();
Base b = *d_ptr; // object slicing, d's methods will become Base methods;
Base* b_ptr = &b;
b_ptr->Update(); // will call Base::Update()

【讨论】:

【参考方案3】:

首先要做的事情。您提供的示例首先不起作用,因为您忘记了指针的实例化。你的意思可能是这样的:

 Base* base = new Object;
 while(1)
 
    base->Update();
 

现在解决这个问题。这个概念应该如您所愿。如果 Update 覆盖了其他人已经指出的 base 中的虚函数,则应在 Object 类中调用 Update。在c++11 中有一个整洁的东西叫做override。它是您在函数声明之后放置的关键字,您希望覆盖基中的某些虚函数。使用override 是一个好习惯,因为如果您尝试使用override 非虚拟函数,编译器会抱怨。这减少了代码出错的可能性。

【讨论】:

以上是关于用 C++ 实现接口?的主要内容,如果未能解决你的问题,请参考以下文章

如何用C++实现支持HTTPS的RESTful WebServer

在 C++11 或以上,有没有办法通过 lambda 实现单方法纯虚拟 C++ 接口?

[ C++ ] STL_stack(栈)queue(队列)使用及其重要接口模拟实现

适配器模式C++实现

适配器模式C++实现

在 C++ 中使用多继承声明接口并实现接口