C++ 条件虚拟继承和对虚拟基成员的访问
让我们看看下面的代码:C++ 条件虚拟继承和对虚拟基成员的访问,c++,inheritance,virtual-inheritance,C++,Inheritance,Virtual Inheritance,让我们看看下面的代码: struct A { A (std::string s) : str {s} {} A () = default; std::string str {"XXX"}; }; struct B1 : virtual A { B1 () = default; void foo_b1 () { std::cout << str << std::endl; } }; struct B2 :
struct A {
A (std::string s) : str {s} {}
A () = default;
std::string str {"XXX"};
};
struct B1 : virtual A {
B1 () = default;
void foo_b1 () {
std::cout << str << std::endl;
}
};
struct B2 : virtual A {
B2 () = default;
void foo_b2 () {
std::cout << str << std::endl;
}
};
struct Empty {};
第(1)行和第(2)行当然不会编译,这正是我想要的,但是如果我取消对第(X)行GCC 4.8.3和Clang 3.5.0的注释,则会使用以下消息拒绝代码:
错误:未在此作用域`#GCC中声明“str”
错误:使用未声明的标识符'str'`
为什么??我从B1或B2继承,我应该有权访问虚拟基成员。所以我在没有条件继承的情况下测试了它
template <typename T>
struct Z : B1, Empty {
Z () : A ("Z ctor") {
std::cout << str << std::endl; // (Y)
}
};
这对于这两种编译器来说都很好。在这种情况下,第(Y)行不会产生任何问题
如果使用条件继承,是否有任何原因导致无法访问虚拟基成员?还是某种编译器错误?
str
是一个依赖名称,因此必须使用this->str
(或a::str
)
否则,您必须直接从A
继承:
template <typename T>
struct X : virtual A,
std::conditional<std::is_integral<T>::value, B1, Empty>::type,
std::conditional<std::is_floating_point<T>::value, B2, Empty>::type {
X () : A ("X ctor") {
std::cout << str << std::endl; // (X)
}
};
模板
结构X:虚拟A,
std::conditional::type,
std::conditional::type{
X():A(“X向量”){
std::cout这不是编译器错误。在您的示例中,std::conditional::type
和std::conditional::type
都是依赖的基类,因为它们依赖于模板参数T
。如当前工作草案§14.6.2所述:
在类或类模板的定义中,在类模板或成员的定义点或类模板或成员的实例化过程中,未在非限定名称查找期间检查从属基类(14.6.2.1)的范围。[示例:
typedef双A;
B类模板{
类型定义INTA;
};
模板结构X:B{
A;//A的类型为double
};
X
定义中的类型名称A
绑定到全局命名空间范围中定义的typedef名称,而不是基类B
中定义的typedef名称-结束示例]
GCC和Clang正确地发出了一个错误,str
未声明,因为编译器实际上是在声明X
之前在全局范围内查找str
的声明
您只需通过编写this->str
或A::str
“gcc 4.8.3和clang 3.5.0拒绝代码”来限定str
,还可以包括在您的问题中发生拒绝时发出的逐字错误消息文本。(请回答您的问题;您知道这是如何工作的)一个猜想:条件继承使<代码> STR >依赖于<代码> t>代码>,因此您可能必须使用<代码> -> STR 访问它。编译器可能会考虑如果<代码> t>代码>有某种类类型。@ BPrassSon“条件继承使STR依赖于T,因此您可能必须使用-> STR访问它。”你说得对。这就解决了问题。这本质上是“什么是从属名称”或其他问题的重复。
template <typename T>
struct Z : B1, Empty {
Z () : A ("Z ctor") {
std::cout << str << std::endl; // (Y)
}
};
Z<int> z;
z.foo_b1 ();
template <typename T>
struct X : virtual A,
std::conditional<std::is_integral<T>::value, B1, Empty>::type,
std::conditional<std::is_floating_point<T>::value, B2, Empty>::type {
X () : A ("X ctor") {
std::cout << str << std::endl; // (X)
}
};
typedef double A;
template<class T> class B {
typedef int A;
};
template<class T> struct X : B<T> {
A a; // a has type double
};