You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何派生类使用using声明后未调用基类const赋值运算符?

CRTP场景下operator=的调用异常分析

关于继承operator=的技术讨论中,普遍结论是基类的operator=会被派生类隐式定义的版本遮蔽,若需使用基类版本,可通过using Base::operator=声明引入。本文讨论CRTP(奇异递归模板模式)场景下的一个特殊问题:

#include <iostream>

template <typename E>
struct A {
    E& operator= (const E& other) {
      std::cout << "A<E>::op=\n";
      return *(E*)this;
    }

    E& operator= (E& other) {
      std::cout << "A<E>::op no const=\n";
      return *(E*)this;
    }
};

struct B : public A<B> {
    using A<B>::operator=;
};

int main () {
  B x, y;
  x = y;
  const B z;
  x = z;
}

在main函数中,x = y会按预期调用E=B时的E& A<E>::operator=(E& other),但x = z却未调用E& A<E>::operator=(const E& other),这一行为的原因是什么?(注:此问题仅关注行为本身,不讨论代码风格)


原因解析

核心问题在于派生类B会被编译器隐式生成一个拷贝赋值运算符,这个隐式版本的签名是B& operator=(const B&),它在重载决议中的优先级高于通过using引入的基类版本:

  1. 隐式生成的拷贝赋值运算符:当派生类未显式定义拷贝赋值运算符时,编译器会自动生成一个,用于处理同类型const对象的赋值操作。
  2. 重载决议的优先级规则:在候选函数匹配时,派生类自身的成员函数比基类的成员函数优先级更高。对于x = z(x为B,z为const B),隐式生成的B& operator=(const B&)是精确匹配,而基类中引入的B& operator=(const B&)属于基类成员,因此会被优先选择。
  3. 非const赋值的匹配逻辑:对于x = y(y为非constB),隐式生成的拷贝赋值运算符仅接受const B&参数,此时基类的B& operator=(B&)是更匹配的候选,因此被调用。

内容的提问来源于stack exchange,提问作者Michaël

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 07:32:43