0

这会引起歧义吗?:

class A { ... };
class B : public A {
//...
B(const B& b);
B(const A& a);
//...
};
4

3 回答 3

4

更新:提问者似乎已经从问题中删除了类名。这是编写此答案的原始代码:

class Vector2D { ... };
class Vector3D : public Vector2D {
//...
Vector3D(const Vector2D& b);
Vector3D(const Vector3D& a);
//...
};

我之前说“不”,但我改变了主意。这是模棱两可的,我想不出一个很好的理由来Vector3D继承 from 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。这在数学上是不合逻辑的。

于 2012-07-28T21:38:24.210 回答
2

在引用基类和派生类型的重载构造函数之间进行选择时,通常没有歧义。

如果参数是派生自基类型 ( A) 但不是派生类型 ( B) 或派生自派生类型的类型,则显然只有引用基的构造函数是匹配的。

如果参数是派生类型,则调用采用基类的构造函数所需的转换需要派生到基类型,此时调用引用派生类型的构造函数只需要标识转换,因此后者是更好的匹配。

如果参数是派生自派生类型 ( B) 的类,那么采用派生类型 () 的构造函数B仍然是更好的匹配,因为标准规定绑定到派生类型的引用比绑定到该类型的基础。(ISO/IEC 14882:2011 13.3.3.2 / 4 - 对隐式转换序列进行排序 [over.ics.rank])

显然,如果你足够努力,你仍然会产生歧义。

例如

struct S {
    operator A() const;
    operator B() const;
};

S s;
B b(s);
于 2012-07-28T23:00:42.777 回答
1

运算符&生成引用。

在您的情况下,第一种类型是对 Vector3D 类型的引用,另一种是对 Vector2D 类型的引用,因此它们是不同的类型。

由于它们是不同的类型,它们会使您的构造函数的签名不同,并且它们不会产生歧义。

答案是不。

于 2012-07-28T21:31:39.553 回答