【问题标题】:Access "this" pointer of concrete class from interface从接口访问具体类的“this”指针
【发布时间】:2015-05-19 02:22:41
【问题描述】:

在编写测试后,我确定接口中的this 指针不等于具体类的this 指针,这意味着我不能只对其使用C 风格的强制转换。

class AbstractBase {...};

class AnInterface {
public:
    AnInterface() {...} // need AbstractBase * here 
    ~virtual AnInterface() {...} // and here
};

class Concrete : public AbstractBase, public AnInterface {};

我的接口需要一个基类指针,指向在构造函数和析构函数中继承它的具体类,以便处理与接口相关的注册和注销。

每一个继承接口的具体对象都需要先继承抽象基类,它在布局中总是排在第一位的。

对于构造函数来说,这并不难,我可以在接口构造函数中添加一个指针,并从具体类中传递this。但是析构函数没有任何参数,所以我在那里一头雾水。

到目前为止,我想出的解决方案都有开销:

1 - 将指针存储在要在析构函数中使用的接口中 - 增加一个指针的内存开销

class AnInterface {
public:
    AnInterface(AbstractBase * ap) {...}
    ~virtual AnInterface() {...} // and here
private:
    AbstractBase * aPtr;
};

...
Concrete() : AnInterface(this) {}

2 - 在接口中创建一个抽象方法并实现它以在具体类中返回this - 增加了虚拟调用的间接开销

class AnInterface {
    virtual AbstractBase * getPtr() = 0;
};

class Concrete : public AbstractBase, public AnInterface {
    AbstractBase * getPtr() { return this; }
};

3 - dynamic_cast 更糟

有没有更有效的方法来实现这一点?

【问题讨论】:

  • 您说,“我的接口需要一个基类指针,指向继承它的具体类”。这似乎是设计中的一个缺陷。
  • @RSahu - 该接口旨在与抽象基类一起使用,但与其设计分离。我不想继承接口中的基类,因为有多个接口会变得乱七八糟。
  • 那么从 AbstractBase 导出 AnInterface 吗?
  • @berkus - 这就是我刚才所说的。它不是唯一使用抽象基的接口,所以如果一个具体类继承了 2 个这样的接口,我将在继承链中有 2 个抽象基......
  • @Bathsheba - 他们不必是,如果他们是就好了,然后我可以 C 转换指针并完成它。

标签: c++ interface base-class concreteclass


【解决方案1】:

IMO 如果确实需要基类和接口之间的解耦,那么解决方案 1 和 2 的开销都可以承受,在现代硬件上肯定不会有任何问题。

但是既然你说接口是设计来与基类提供的功能一起工作的,那么解耦可能不是一件好事。

我的意思是如果问题在于继承多个接口,这些接口都继承了基类or the "dreaded diamond" problem with inheritance, you can simply use virtual inheritance

【讨论】:

    【解决方案2】:

    您的所有顾虑似乎都是微优化。假设您确实无法将接口与实现分开(在这种情况下,您为什么首先使用接口?)我只会使用dynamic_cast 并完成它,即使它非常重量级。如果我被困在一个不能选择 RTTI 的平台上,那么我会使用选项 2。

    【讨论】:

      【解决方案3】:

      你的设计有一些缺陷。

      您应该考虑使用CRTP as from the Mixin aspect,这样您就不必保留一个额外的具体派生指针。

      template<typename Derived>
      class AnInterface {
      public:
          AnInterface() {
             Derived* derived = static_cast<Derived*>(this);
             AbstractBase* abstractBase = static_cast<AbstractBase*>(derived);
          } // have AbstractBase * here 
          ~virtual AnInterface() {...} // and here
      };
      
      class Concrete 
      : public virtual AbstractBase
      , public AnInterface<Concrete> {
          AbstractBase * getPtr() { return this; }
      };
      

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-04
      • 1970-01-01
      • 1970-01-01
      • 2023-03-18
      • 1970-01-01
      • 1970-01-01
      • 2020-01-15
      • 1970-01-01
      相关资源
      最近更新 更多