提问人:Adrian McCarthy 提问时间:8/21/2023 最后编辑:Adrian McCarthy 更新时间:8/21/2023 访问量:37
对比解决方案,用于从基类模板继承时的可见性
Contrasting solutions for visibility when inheriting from base class templates
问:
在下面的代码中,编译将失败,因为尽管有公共继承链,但 HasFlag 在 DerivedFoo 中不可见。
class BasicFoo {
public: bool HasFlag() const { return m_flag; }
private: bool m_flag = false;
};
template <typename T>
class Foo : public BasicFoo {
public: bool Test() const { return HasFlag(); }
};
template <typename T>
class DerivedFoo : public Foo<T> {
public:
// HasFlag is not visible here.
bool Test2() const { return HasFlag(); }
};
为什么会这样,在其他问题中也有介绍。我的问题是这两种解决方案之间是否有任何区别:
// Option 1: Explicitly pull it into scope from immediate base.
using Foo<T>::HasFlag;
bool Test2() const { return HasFlag(); }
// Option 2: Explicitly pull it from the root class.
using BasicFoo::HasFlag;
bool Test2() const { return HasFlag(); }
从不是类模板的根类中提取方法是否在某种程度上更有效?只有一个 BasicFoo::HasFlag。如果为许多 T 实例化了 DerivedFoo<T>,则实际上存在许多相同的 Foo<T>::HasFlags。这重要吗?
答:
1赞
Jan Schultke
8/21/2023
#1
从语义上讲,这两种解决方案是等价的。它们都是 using 声明,使成员在派生类中可用。HasFlag
using BasicFoo::HasFlag;
不过,这可能会更好,因为它不依赖于 ,并且编译器可以在实例化类模板之前诊断该成员是否存在。从直觉上讲,这应该会稍微快一些,尽管它不太可能产生任何明显的差异。如有疑问,请对您的编译进行基准测试(例如,使用 LLVM 的)。T
HasFlag
BasicFoo
DerivedFoo
-ftime-trace
如果实例化了许多 s,则实际上有许多相同的 .
DerivedFoo<T>
T
Foo<T>::HasFlags
事实并非如此;中只有一个成员。这两种解决方案之间的区别仅在于名称查找,而不在于创建的成员数量。HasFlag
BasicFoo
替代解决方案
bool Test2() const {
// access to this makes HasFlag() dependent on T, so this won't fail to compile
return this->HasFlag();
}
bool Test2() const {
// qualified lookup also forces a delayed check, making this compile
return BasicFoo::HasFlag();
}
评论
0赞
Adrian McCarthy
8/21/2023
谢谢,关于可能使编译器推迟 DerivedFoo 实例化的一点达到了我所追求的核心。我知道您包含的替代解决方案,但我也在尝试向 DerivedFoos 的用户公开 HasFlag。
评论
DerivedFoo<
T>,则实际上存在许多相同的Foo<T>::HasFlags
。这是错误的。 不是由 定义的,因此实例化不会实例化很多。HasFlags
Foo<T>
Foo<T>
HasFlags
DerviedFoo
return this->HasFlags();
HasFlags
DerviedFoo::Test2
Foo<T>
HasFlags
Foo
BasicFoo
HasFlags
DerivedFoo<int> d; d.HasFlag();
HasFlag
this->HasFlags()
using