为何部分编译器中,模板派生类的using声明未按预期生效?
从类模板派生时访问基类成员的三种解决方法
嘿,这个问题我太熟了!当你从类模板派生的时候,基类的成员为啥非得用Base::或者this->来限定?核心原因就是这些基类成员属于「模板依赖名称」——编译器在实例化模板之前,没法确定基类的具体结构(毕竟基类是带模板参数的),所以得靠这些限定符给编译器指明方向:“这个成员是从我的基类里来的哈!”
不过你说的没错,除了Base::和this->,确实还有第三种好用的办法——using声明。我结合你给的代码片段,把三种方法都演示一遍:
先把基础代码补全:
struct Gadget { void gadge() { } }; struct Base1 { Gadget g; }; template<typename T> struct Base2 : Base1 { };
方法1:用Base::限定基类成员
直接在访问成员时加上基类模板的限定,明确告诉编译器成员的来源:
template<typename T> struct Widget : Base2<T> { void func() { // 明确指定g来自Base2<T> Base2<T>::g.gadge(); } };
方法2:用this->限定基类成员
this指向当前对象,通过它访问基类继承来的成员,编译器会自动去依赖的基类里查找:
template<typename T> struct Widget : Base2<T> { void func() { // 通过this指针访问继承的g成员 this->g.gadge(); } };
方法3:用using声明引入基类成员
在派生类模板里用using声明把基类的成员引入当前作用域,之后就可以直接访问,不用每次都加限定符,代码更清爽:
template<typename T> struct Widget : Base2<T> { // 把Base2<T>里的g成员引入当前类的作用域 using Base2<T>::g; void func() { // 直接访问g就行,编译器已经知道它来自基类 g.gadge(); } };
这种using声明特别适合需要多次访问同一个基类成员的场景,写一次就够,不用重复写限定符,代码可读性也更高。
内容的提问来源于stack exchange,提问作者rubix_addict
相关产品推荐
相关产品推荐

