AnT*_*AnT 48
如果"非法"是指形成不良,那么如果基类无法访问或含糊不清则属于非法行为.
例如,当基类是私有时,它是不可访问的.
class A {};
class B : A {};
...
B b;
A *pa = &b; // ERROR: base class is inaccessible
Run Code Online (Sandbox Code Playgroud)
请注意,即使在C++ 11中,C风格的强制转换也可以"突破"访问保护并执行正式的正确向上转换
A *pa = (A *) &b; // OK, not a `reinterpret_cast`, but a valid upcast
Run Code Online (Sandbox Code Playgroud)
当然,应该避免这种用法.
如果源类型包含目标类型的多个基础子对象(通过多重继承),则不明确.
class A {};
class B : public A {};
class C : public A {};
class D : public B, public C {};
D d;
A *pa = &d; // ERROR: base class is ambiguous
Run Code Online (Sandbox Code Playgroud)
在这种情况下,可以通过明确地"行走"所需的上行路径和中间上行到基点不再模糊的点来执行上行扫描.
B* pb = &d;
A* pa = pb; // OK: points to 'D::B::A' subobject
Run Code Online (Sandbox Code Playgroud)Che*_*Alf 17
如果基类不明确(通过不同路径继承两次或更多次),则无法在一个步骤中进行向上转换.
如果基类不可访问,则转发的唯一方法是使用C样式转换.这是该演员的一个特例,它是唯一可以完成这项工作的人.从本质上讲,它的行为static_cast不受可访问性的限制.
Standardese.
C++11§5.4/ 4:
" ...在[C cast]中执行a
static_cast在以下情况下,即使基类不可访问,转换也是有效的:
- 指向派生类类型的对象的指针或派生类类型的左值或右值可以分别显式转换为指针或对明确基类类型的引用;
- 指向派生类类型成员的指针可以显式转换为指向非明确的非虚基类类型成员的指针;
- 指向明确的非虚基类类型的对象的指针,明确的非虚基类类型的glvalue,或指向非明确的非虚基类类型的成员的指针可以被显式转换为指针,a引用或指向派生类类型成员的指针.
歧义的例子:
struct Base {};
struct M1: Base {};
struct M2: Base {};
struct Derived: M1, M2 {};
auto main() -> int
{
Derived d;
//static_cast<Base&>( d ); //! Ambiguous
static_cast<Base&>( static_cast<M2&>( d ) ); // OK
}
Run Code Online (Sandbox Code Playgroud)
无法访问的基础示例,在演员阵容中进行(通常)地址调整:
struct Base { int value; Base( int x ): value( x ) {} };
class Derived
: private Base
{
public:
virtual ~Derived() {} // Just to involve an address adjustment.
Derived(): Base( 42 ) {}
};
#include <iostream>
using namespace std;
auto main() -> int
{
Derived d;
Base& b = (Base&) d;
cout << "Derived at " << &d << ", base at " << &b << endl;
cout << b.value << endl;
};
Run Code Online (Sandbox Code Playgroud)
Ded*_*tor 10
有两种情况,在C++中编译不正确(在编译时诊断):
无法访问有问题的基类:
class base {};
class derived : base {};
int main() {
derived x;
base& y = x; // invalid because not accessible.
// Solution: C-style cast (as static_cast without access-check)
base& y1 = (base&)x;
}
Run Code Online (Sandbox Code Playgroud)有问题的基类子对象不是明确的:
class base {};
struct A1 : base {};
struct A2 : base {};
struct derived : A1, A2 {};
int main() {
derived x;
base& y = x; // invalid because ambiguous.
// Solution 1, scope resolution:
base& y1 = static_cast<A1::base&>(x);
base& y2 = static_cast<A2::base&>(x);
// Solution 2, intermediate unambiguous steps:
A1& a1 = x;
A2& a2 = x;
base& ya1 = a1;
base& ya2 = a2;
}
Run Code Online (Sandbox Code Playgroud)