这会引起歧义吗?:
class A { ... };
class B : public A {
//...
B(const B& b);
B(const A& a);
//...
};
答案 0 :(得分:4)
更新:似乎提问者已从问题中清除了班级名称。以下是编写本答案的原始代码:
class Vector2D { ... };
class Vector3D : public Vector2D {
//...
Vector3D(const Vector2D& b);
Vector3D(const Vector3D& a);
//...
};
我之前说过“不”,但我改变了主意。这是不明确的,我想不出有Vector3D
从Vector2D
继承的充分理由。
从数学角度来看,2D矢量空间可以扩展到3D矢量空间,但有许多扩展可供选择 - 它们不是唯一的。因此,当您创建一个继承自2D矢量类的3D矢量类时,您将在3D空间中嵌入2D空间“特权”,并将所有其他嵌入设置为较差。我认为这不是特别有用。
你正在做的另一件事是你说“每个3D矢量都是一个2D矢量”,这只是一种愚蠢的行为。例如,也许你写一个函数:
// Compute the angle between two vectors
double angle(Vector2D x, Vector2D y);
假设您忘记编写3D矢量版本。现在,编译器将无法向您显示错误消息:相反,您使用创建类时选择的“特权”投影将3D矢量投影到2D空间中,您将得到错误的答案。现在假设您添加了另一个函数:
// Compute the angle between two 3D vectors
double angle(Vector3D x, Vector3D y);
现在,还有一个问题。
Vector3D x = ...;
Vector2D y = ...;
double a = angle(x, y);
这将使用x的2D投影,同样,您将不会收到编译器警告。你只会得到错误的答案。
摘要:这是最糟糕的歧义:编译器将为您提供您不期望的答案,这是一种模糊性。
Vector3D不应该从Vector2D继承。这在数学上是不合逻辑的。
答案 1 :(得分:2)
在选择引用基类和派生类型的重载构造函数时,通常没有歧义。
如果参数是从基类型(A
)派生的类型而不是从派生类型(B
)派生的类型或从派生类型派生的类型,那么显然只有构造函数采用对base的引用是匹配。
如果参数是派生类型,那么调用构造函数获取基类所需的转换需要一个派生到基类型,其中对构造函数的调用仅需要一个标识转换所以后者是更好的匹配。
如果参数是从派生类型(B
)派生的类,那么采用派生类型(B
)的构造函数仍然是更好的匹配,因为标准表示绑定到引用派生类型的绑定比绑定到该类型的基础的引用更好。 (ISO / IEC 14882:2011 13.3.3.2 / 4 - 对隐式转换序列进行排序[over.ics.rank])
如果你努力尝试,显然你仍然会产生歧义。
E.g。
struct S {
operator A() const;
operator B() const;
};
S s;
B b(s);
答案 2 :(得分:1)
运算符&
生成引用。
在你的情况下,第一种类型是对Vector3D类型的引用,另一种是对Vector2D类型的引用,因此它们是不同的类型。
由于它们是不同的类型,它们会使构造函数的签名不同,而且它们也不会产生歧义。
答案是否。