首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >编译器如何在内部解决C++中的菱形问题?

编译器如何在内部解决C++中的菱形问题?
EN

Stack Overflow用户
提问于 2011-09-12 14:00:53
回答 3查看 2.8K关注 0票数 11

我们知道我们可以使用虚拟继承来解决钻石问题。

例如:

代码语言:javascript
运行
复制
   class Animal // base class
   {
     int weight;
     public:
     int getWeight() { return weight;};
   };
   class Tiger : public Animal { /* ... */ }; 
   class Lion : public Animal { /* ... */ };
   class Liger : public Tiger, public Lion { /* ... */ }; 
   int main()
   {
     Liger lg ;
     /*COMPILE ERROR, the code below will not get past
     any C++ compiler */
     int weight = lg.getWeight();
   }

当我们编译这段代码时,我们会得到一个歧义错误。现在我的问题是编译器如何在内部检测这个歧义问题(菱形问题)。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-09-12 14:21:06

编译器构建列出每个类的所有成员的表,并且还具有允许它在任何类的继承链上上下移动的链接。

当需要定位一个成员变量(在你的例子中是weight)时,编译器从实际的类开始,在你的例子中是Liger。它不会在那里找到权重成员,因此它会向上移动一级到父类。在本例中,有两个成员,因此它同时扫描Tiger和Lion以查找name weight的成员。仍然没有任何点击,所以现在它需要再上一级,但它需要做两次,在这个级别上的每个类一次。这将一直持续下去,直到在继承树的某个级别找到所需的成员。如果在任何给定的级别上,它只找到一个成员,考虑到所有多个继承分支,一切都很好,如果它找到两个或更多具有所需名称的成员,则它无法决定选择哪个成员,因此它出错。

票数 4
EN

Stack Overflow用户

发布于 2011-09-12 14:05:24

当编译器为一个类创建一个函数指针表时,每个符号必须在其中恰好出现一次。在本例中,getWeight出现了两次:在Tiger中和在Lion中(因为Liger没有实现它,所以它向上树查找它),因此编译器被卡住了。

实际上,这很简单。

票数 3
EN

Stack Overflow用户

发布于 2011-09-12 15:10:21

在您的代码中,liger的结构是

代码语言:javascript
运行
复制
Liger[Tiger[Animal]Lion[Animal]]

如果你从一个Liger指针调用一个Animal函数,那么Liger实际上可以转换成两个动物(因此有歧义)

虚拟继承将生成如下结构

代码语言:javascript
运行
复制
Liger[Tiger[*]Lion[Animal]]
            \-----/

现在只有一个动物,可以从两个基地间接到达,所以从Liger到动物的转换不再是模棱两可的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7383840

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档