继承 - 为什么这是非法的
Inheritance - why is this illegal?
我正在做一个C++测验。并遇到了以下代码 - 这是非法的,但我不明白为什么。谁能解释为什么这行:
Box* b1 = s1->duplicate();
生成编译器错误"无法从 Shape* 转换为 Box"?我假设s1->duplicate()
正在调用Box::duplicate()
s1
因为它实际上指向一个Box
- 但从编译器错误来看,它似乎在调用Shape::duplicate()
。
#include <iostream>
struct Shape
{
virtual Shape* duplicate()
{
return new Shape;
}
virtual ~Shape() {}
};
struct Box : public Shape
{
virtual Box* duplicate()
{
return new Box;
}
};
int main(int argc, char** argv)
{
Shape* s1 = new Box;
Box* b1 = s1->duplicate();
delete s1;
delete b1;
return 0;
}
C++语言是静态类型的。有关调用合法性的决定是在编译时做出的。显然,编译器无法知道s1->duplicate()
返回指向Box
对象的指针。在这种情况下,期望它接受您的代码是不合逻辑的。
是的,在您的示例中确实s1->duplicate()
调用Box::duplicate
,但是您如何期望编译器知道这一点?从您的具体示例中可以说它是"显而易见的",但是此语言功能的规范对于此类"明显"的情况也不例外。
Shape::duplicates()
返回一个Shape*
,这不是一个Box*
。实际返回的运行时类型与它无关。编译器怎么知道返回的Shape*
实际上指向Box
?
编辑:想想这个:
struct Shape
{
virtual Shape* duplicate()
{
return new Shape;
}
virtual ~Shape() {}
};
struct Box : public Shape
{
virtual Box* duplicate()
{
return new Box;
}
};
struct Sphere : public Shape
{
virtual Sphere* duplicate()
{
return new Sphere;
}
};
Shape* giveMeABoxOrASpehere()
{
if ( rand() % 2 )
return new Box;
else
return new Sphere;
}
//
Shape* shape = giveMeABoxOrASphere();
// What does shape->duplicate() return?
Box* shape = giveMeABoxOrASphere();
// shoud this compile?
出于完全相同的原因
Shape* s1 = new Box;
Box* b1 = s1;
不编译。编译器不在乎s1
指的是Box
,也不应该在乎。
如果你知道s1
指的是一个Box
,就说出来:
Box *s1 = new Box;
关于语法的说明:Box * s1;
的解析规则是(非常简化):
declaration := type-name declarator ;
declarator := name
| * declarator
所以解析是:
Box * s1 ;
^^^^^^^^
declarator
^^^^^^^^^ ^^^^^^^^^^^^^^^^^^
type-name declarator
并且分组Box (* (s1) )
编写Box *s1;
被认为是最佳样式,因为它与解析比Box* s1;
更一致 如果在一个声明中声明多个变量,则Box*
语法可能会令人困惑:
Box* x, y;
x
是指向Box
的指针,但y
是Box
,因为解析是:
Box (*x), y;
相关文章:
- 为什么基于范围类型的大括号上循环init列表是非法的c++
- 为什么代码会抛出非法内存访问错误
- 为什么派生类的这个定义是非法的
- 为什么是非法的:将指针向量复制到指向常量的指针向量中
- 学习C :为什么这是非法的
- 为什么使用构造函数调用表示法定义指向指针变量的指针是非法的
- C++ 为什么反转路径是非法的
- 为什么Folloing代码在2010年Visual Studio(X64应用程序)中抛出非法指令例外
- 为什么vector<int * const>是非法/不合逻辑的?
- 继承 - 为什么这是非法的
- C++:为什么构造"A(A a) {}"是非法的?
- 为什么 如果类的成员是引用,则复制对象是非法的
- 在下面的代码上下文中,为什么"cout << c"是合法的,而"c = "x"是非法的?
- 为什么double v2=((double)51/4)%2是非法表达式ni c++
- 为什么int&r = 0是非法的,而const int&r = 0是合法的?
- 如果C++向后兼容C,那么为什么在C++中void main是非法的
- 为什么这个c++赋值语句是非法的
- 为什么带逗号的双重初始化是非法的?
- 为什么编译器说"非法使用浮点"?
- 为什么非模板化函数具有相同的名称和参数但不同的返回类型是非法的?(但对模板函数合法吗?)