- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我看到的大多数关于成员指针的讨论都集中在成员所属类型允许的转换上。我的问题是关于成员(member)类型的转换。
struct Base{};
struct Derived : public Base{};
struct Foo{ Derived m_Derived; };
鉴于这些声明,以下代码会产生错误 (MSVC 2008):
// error C2440: 'initializing' : cannot convert from 'Derived Foo::* ' to 'Base Foo::* '
Base Foo::*p = &Foo::m_Derived;
通常允许从 Derived* 到 Base* 的转换 - 为什么这里有区别?
最佳答案
你的方差向后。
返回类型隐式转换为基本类型(逆变)。但是参数隐式转换为派生类型(协变),指向成员的指针中的类类型充当参数。为了解这一点,让我们应用 Liskov 可替代性原则:
Base*
的约定是:“我给你一个Base”(当你对我使用*
操作符时)。Derived*
的约定是“我给你一个Derived,也是一个Base”。
显然 Derived*
可以用来代替 Base*
。因此,存在从 Derived*
到 Base*
的隐式转换。
但是考虑指向成员的指针的契约。
int Base::*
的契约是:“给我一个 Base,我会还给你一个 int”(派生是一个 Base,所以那些也可以)int Derived::*
的契约是:“给我一个 Derived,我会还给你一个 int”(但不是任何旧的 Base
都可以,它必须是派生
)
假设您有一个 Base
而不是 Derived
。它在取消引用 int Base::*
时会很好地工作,但不能与 int Derived*
一起使用。
但是,如果您有一个
Derived
,您可以使用它来取消引用
int Base::*
和
int Derived::*
。因此,存在从
int Base::*
到
int Derived::*
的隐式转换
哎呀,我按照你说的做了,分析了成员(member)属于什么类型。
LSP 仍然有效。我同意转换应该是合法的,至少根据类型安全。契约(Contract)是“给我一个
Foo
,我会给你一个
Derived
”,显然你可以用它来从
Foo
到
>Base
通过将其与隐式转换组合在一起。所以很安全。 DeadMG 可能在正确的轨道上指出了基础子对象的关系位置的潜在复杂性,尤其是在虚拟继承中。但是指向成员的指针在取消引用运算符的 LHS 上处理这些问题,因此它们也可以处理结果。
最终的答案可能只是标准不要求转换是合法的。
关于c++ - 指向数据成员与非成员的指针的隐式转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4403786/
我是一名优秀的程序员,十分优秀!