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

无法使用赋值语法通过派生类shared_ptr构造对象,如何解决?

问题分析与解决办法

问题原因

A a1(data)属于直接初始化,C++允许这个过程中进行一次隐式转换:std::shared_ptr<derived>可以隐式转换为std::shared_ptr<base>,随后调用A的构造函数,因此编译通过。

而A a2 = data属于拷贝初始化,这个过程需要两次连续的隐式转换:先将std::shared_ptr<derived>转为std::shared_ptr<base>,再将后者转为A实例。但C++标准规定,拷贝初始化仅允许一次用户定义的隐式转换,因此这行代码编译失败。

解决办法

办法1:显式转换data类型

通过显式将data转为std::shared_ptr<base>,让拷贝初始化仅需一次转换:

#include <memory>

struct base {
  virtual ~base() {}
};

struct derived : public base {};

struct A {
  A(std::shared_ptr<base> x) {}
};

int main() {
  std::shared_ptr<derived> data = std::make_shared<derived>();
  A a1(data);  // ok
  A a2 = static_cast<std::shared_ptr<base>>(data); // 显式转换后可正常编译
  return 0;
}

办法2:为A添加模板构造函数

新增模板构造函数,直接接受任意继承自base的std::shared_ptr<T>,避免两次隐式转换:

#include <memory>
#include <type_traits>

struct base {
  virtual ~base() {}
};

struct derived : public base {};

struct A {
  A(std::shared_ptr<base> x) {}
  
  // 模板构造函数,仅匹配继承自base的类型
  template<typename T, typename = std::enable_if_t<std::is_base_of_v<base, T>>>
  A(std::shared_ptr<T> x) : A(std::static_pointer_cast<base>(x)) {}
};

int main() {
  std::shared_ptr<derived> data = std::make_shared<derived>();
  A a1(data);  // ok
  A a2 = data; // 现在可正常编译
  return 0;
}

办法3:直接构造临时A实例

拷贝初始化可以直接接受临时A对象,此时仅需一次隐式转换(data转std::shared_ptr<base>构造临时A):

#include <memory>

struct base {
  virtual ~base() {}
};

struct derived : public base {};

struct A {
  A(std::shared_ptr<base> x) {}
};

int main() {
  std::shared_ptr<derived> data = std::make_shared<derived>();
  A a1(data);  // ok
  A a2 = A(data); // 构造临时A,可正常编译
  return 0;
}

内容的提问来源于stack exchange,提问作者mxmxlwlw

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 20:52:34