【问题标题】:Return reference to this and inheritance返回对 this 和继承的引用
【发布时间】:2012-02-13 17:43:57
【问题描述】:

对于一些语法糖,我想返回一个对this的引用,但是当被继承时,函数应该返回子类的类型:

class base {
  T &operator!() { return *this; }
};
base b; b = !b;

class child : public base {};
child c; c = !c;

由于操作符,我不能只返回指针和动态转换它,它必须是一个引用。

这可能吗?将decltype(*this) 用于T 不起作用,auto f()->decltype(*this) 也不起作用,因为this(虽然我不明白为什么,在自动情况下)

在 Scala 中,您可以编写如下内容:

template<typename T> class base {
  T &f() { return *this; }
};
class child : public base<child> {};

但我的 g++ 不会接受这个(不确定这是错误还是规范中没有?)

当然有显式方式,但我想知道是否可以使用 C++11 特性来避免这种情况?

class child : public base {
  child &operator!() { base::operator!(); return *this }
};

【问题讨论】:

  • 请不要以改变其基本含义的方式覆盖运算符。这是一个非常糟糕的主意,会导致混乱和错误。
  • 在这种情况下它是一个 DSL 的东西,我实际上使用 &&,即使它不返回布尔值,它在语义上的意思是“和”

标签: c++ templates crtp static-polymorphism


【解决方案1】:

如果允许您将base 设为模板,您可以使用 CRTP 执行此操作:

template <typename Derived> class Base {
protected:
    Derived& refToThis() {
        return *static_cast<Derived*>(this);
    }
};

注意这里的额外演员。这样做的原因是,如果您有这样的课程:

class Subclass: public Base<Subclass> {
    /* ... */
};

然后,如果您从该类内部调用refToThis,它将调用基类版本。由于类继承自Base&lt;Subclass&gt;refToThis 的实例化模板将是

    Subclass& refToThis() {
        return *static_cast<Subclass*>(this);
    }

这段代码是安全的,因为this 指针确实指向Subclass 对象。此外,如果派生类没有从Base 正确继承,static_cast 将确保转换在编译时失败,因为指针类型不可转换。

这里需要演员表的原因是,如果你只是说

template <typename Derived> class Base {
protected:
    Derived& refToThis() {
        return *this;
    }
};

然后程序中有一个类型错误,因为 Base 本身 不是 Derived,如果你可以将 Base&amp; 转换为 Derived&amp; 而没有任何检查你可能会破坏类型系统。

也就是说……我根本不会这样做。为此重载operator! 会降低代码的可读性,而仅仅编写*this 是非常惯用的,隐藏它会使您的代码更难理解。使用所有这些模板机制来避免常见的 C++ 似乎是错误的。如果您在返回引用之前正在做其他事情,那很好,但这似乎不是一个好主意。

希望这会有所帮助!

【讨论】:

  • 谢谢,我的代码中有一些干扰导致class Subclass: public Base&lt;Subclass&gt; 行出现错误,我担心这在 C++ 中是不可能的。
【解决方案2】:

请不要这样做。已经有一种方法可以用 *whatever_pointer_you_want_to_use_this_crazy_operator_upon 语言来实现。用这种语言创建一种新的做事方式只会让你未来的维护者感到困惑。 else 你真的想在这里实现什么吗?

【讨论】:

  • 我真正想做的是a &lt;&lt; b &lt;&lt; c &lt;&lt; d,其中&lt;&lt; 运算符在基类中定义并继承,但是我需要左侧的子类型,不像ostream
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-08
  • 1970-01-01
  • 2014-05-27
  • 1970-01-01
  • 1970-01-01
  • 2019-04-26
  • 1970-01-01
相关资源
最近更新 更多