模板继承基类时,派生类构造函数初始化基类成员及引用基类成员的问题
模板继承基类时,派生类构造函数初始化基类成员及引用基类成员的问题
你这段代码里遇到了两个典型的C++模板继承相关问题,我来帮你拆解并解决:
第一个问题:构造函数初始化列表不能直接初始化基类成员
你在derived的构造函数里写: a{2},编译器会认为a是derived自己的成员变量,但实际上它属于基类ImplType。派生类的初始化列表只能初始化自身的成员或者调用基类的构造函数,不能直接操作基类的成员。
解决这个问题有两种思路:
- 思路一:给基类添加带参数的构造函数,然后在派生类初始化列表里调用它:
struct base { int a; // 新增构造函数,用来初始化a base(int val) : a{val} {} }; template <typename ImplType> struct derived : public ImplType { derived() : ImplType{2} // 调用基类构造函数,间接初始化a {} // ... 其他代码 }; - 思路二:如果不想修改基类,可以在派生类的构造函数体里给
a赋值(因为a是public权限):template <typename ImplType> struct derived : public ImplType { derived() { this->a = 2; // 用this->明确指向基类的a } // ... 其他代码 };
第二个问题:模板派生类中访问基类依赖成员的语法
在模板派生类里,由于ImplType是模板参数(属于依赖类型),编译器不会默认去基类里查找a这个成员。哪怕你写了ImplType::a,有些编译器也可能无法正确解析(或者需要额外的提示)。
常用的解决方法有两种:
- 方法一:用
this->访问成员,编译器会沿着继承链去查找a:auto print() { std::cout << this->a << std::endl; } - 方法二:在派生类中添加
using声明,把基类的a引入当前类的作用域:template <typename ImplType> struct derived : public ImplType { using ImplType::a; // 将基类的a引入当前作用域 derived() : a{2} // 现在可以直接在初始化列表里用a了 {} auto print() { std::cout << a << std::endl; } };
完整修正后的代码示例
这里给你一个用using声明的完整可运行版本,不需要修改基类:
#include <iostream> #include <string_view> #include <memory> #include <string> struct base { int a; }; template <typename ImplType> struct derived : public ImplType { using ImplType::a; derived() : a{2} {} auto print() { std::cout << a << std::endl; } }; int main() { derived<base> d{}; d.print(); // 输出2 }
备注:内容来源于stack exchange,提问作者glades
相关产品推荐
相关产品推荐

