多继承的构造顺序??!!!

时间:2021-07-08 19:29:33
#include <iostream>
using namespace std;

class A
{
public:
void f();
};
void A::f()
{
cout<<"A:f()\n";
}

class B:virtual public A
{
public:
void f();
};
void B::f()
{
cout<<"B:f()\n";
}
class C:public B
{
};
class D:virtual public A,public C
{
public:
void g();
};
void D::g()
{
cout<<"D:g()\n";
f();
}
int main()
{
D d;
d.f();
return 0;
}
请问:为什么输出来老是B::f(),而不是A::f();
构造顺序是怎么样的;为什么会这样呀??
请大家帮忙解释一下了;

15 个解决方案

#1


B中把A中的函数给隐藏了

#2


奇怪了,不懂,帮你顶。
单步执行的话,看着是从a开始建立的,不过就是step不进a的构造函数。

#3


class D:public C,virtual public A
class D:virtual public A,public C
为什么这样换一下,运行出来都是B::f()

#4


B重载了A的f()函数
void B::f()
{
cout<<"B:f()\n";
}

#5


应该是在构造D d 时已经重载了B::f()

#6


你的函数不是虚拟的

#7


这跟构造函数有什么关系-_-

#8


非虚拟函数是静态绑定的

#9


唉,倒底是为什么,不与继承的构造顺序有关,与什么有关??
回复人: xmlhb() ( ) 信誉:100  2004-12-14 13:10:00  得分: 0  
 
 
   非虚拟函数是静态绑定的
  
 
能不能说明天点哟?谢谢离!

#10


class B:virtual public A
{
public:
void f();
};
void B::f()
{
cout<<"B:f()\n";
}

这是原因

你想调用A里面的f()可以:d.A::f();

#11


A
                / \
                B  \  
                \   \
                 C   \
                  \  /
                    D
按所谓的支配原则,直接基类的函数名要“覆盖”间接基类的函数名,但这里A既是D的直接基类,又是继承比较深的间接基类,当然是虚基类了,这个就要看哪个优先了,不过相关的原则我没有看到,可以多试试不同的编译器。
在VC中是B::f()屏蔽了A::f(),不知在dev-c++中是不是这样的,:(

我翻了象C++编程思想,BS的TC++PL,C++语言的设计与演化等书,好象没有看到有关的解释(也有可能我翻得不够仔细)。没有看到类似的例子!

#12



                 A
                / \
                B  \  
                \   \
                 C   \
                  \  /
                    D
按所谓的支配原则,直接基类的函数名要“覆盖”间接基类的函数名,但这里A既是D的直接基类,又是继承比较深的间接基类,当然是虚基类了,这个就要看哪个优先了,不过相关的原则我没有看到,可以多试试不同的编译器。
在VC中是B::f()屏蔽了A::f(),不知在dev-c++中是不是这样的,:(

我翻了象C++编程思想,BS的TC++PL,C++语言的设计与演化等书,好象没有看到有关的解释(也有可能我翻得不够仔细)。没有看到类似的例子!


#13


g++ 3.3.1 的结果是 B::f()

#14


已提交了值班室了,呵

#15


http://community.csdn.net/Expert/topic/3485/3485828.xml?temp=.7147486
虚基类层次的问题是把初始化共享虚资对象的职责转推到每个后续的派生类中。举例来说,我定义了一个基类,它的初始化需要分配一个缓冲区,用户指定的缓冲区的大小作为构造函数的一个参数传递。如果我实现了两个后续的虚继承,名字是inputb和outputb,每个都需要传递给基类构造函数一个特定的值。现在我定义一个派生自inputb和outputb两者的in_out类,那么两个本应传递给共享的基类子对象值都没有生效。

因此,在原始语言设计中,Stroustrup禁用了派生类构造函数的成员初始化类表中,虚基类成员的显式初始化。虽然这解决了这个问题,但是实际上无法控制虚基类,这被证明为是不可行的。国家健康研究所(译者:C++的普及可见一斑)的Keith Gorlen,一个叫做nihcl的免费版本SmallTalk集合库的实现者,是劝告Bjarne,让他必须考虑一个更灵活的语言设计的主要人员之一。

一个面向对象的层次设计的原则之一是一个派生类只应该涉及其本身和直接基类的非私有成员。为了支持一个灵活的虚继承设计,Bjarne 不得不破坏了这个原则。层次中最底层的类负责初始化所有虚对象,不管他们在层次中是哪一级。例如,inputb和outputb都有责任显式初始化他们的直虚接基类。在从inputb 和outputb派生in_out类的时候,in_out开始有责任进行一度被移除的虚基类初始化,并且inputb和outputb中的显式初始化被抑制了。

这提供了语言开发者需要的灵活性,但是以语义的复杂化为代价。如果我们限定虚基类必须没有状态,并且只允许指定一个接口,那么这个负担就被去掉了。这在C++中是一个推荐的设计方案。在C++/CLI中,这是Interface类型的方针。

去看看五星级人物的回答,反正我看了等于白看,就是说这一点由语言?(或编译器)开发者灵活掌握????

#1


B中把A中的函数给隐藏了

#2


奇怪了,不懂,帮你顶。
单步执行的话,看着是从a开始建立的,不过就是step不进a的构造函数。

#3


class D:public C,virtual public A
class D:virtual public A,public C
为什么这样换一下,运行出来都是B::f()

#4


B重载了A的f()函数
void B::f()
{
cout<<"B:f()\n";
}

#5


应该是在构造D d 时已经重载了B::f()

#6


你的函数不是虚拟的

#7


这跟构造函数有什么关系-_-

#8


非虚拟函数是静态绑定的

#9


唉,倒底是为什么,不与继承的构造顺序有关,与什么有关??
回复人: xmlhb() ( ) 信誉:100  2004-12-14 13:10:00  得分: 0  
 
 
   非虚拟函数是静态绑定的
  
 
能不能说明天点哟?谢谢离!

#10


class B:virtual public A
{
public:
void f();
};
void B::f()
{
cout<<"B:f()\n";
}

这是原因

你想调用A里面的f()可以:d.A::f();

#11


A
                / \
                B  \  
                \   \
                 C   \
                  \  /
                    D
按所谓的支配原则,直接基类的函数名要“覆盖”间接基类的函数名,但这里A既是D的直接基类,又是继承比较深的间接基类,当然是虚基类了,这个就要看哪个优先了,不过相关的原则我没有看到,可以多试试不同的编译器。
在VC中是B::f()屏蔽了A::f(),不知在dev-c++中是不是这样的,:(

我翻了象C++编程思想,BS的TC++PL,C++语言的设计与演化等书,好象没有看到有关的解释(也有可能我翻得不够仔细)。没有看到类似的例子!

#12



                 A
                / \
                B  \  
                \   \
                 C   \
                  \  /
                    D
按所谓的支配原则,直接基类的函数名要“覆盖”间接基类的函数名,但这里A既是D的直接基类,又是继承比较深的间接基类,当然是虚基类了,这个就要看哪个优先了,不过相关的原则我没有看到,可以多试试不同的编译器。
在VC中是B::f()屏蔽了A::f(),不知在dev-c++中是不是这样的,:(

我翻了象C++编程思想,BS的TC++PL,C++语言的设计与演化等书,好象没有看到有关的解释(也有可能我翻得不够仔细)。没有看到类似的例子!


#13


g++ 3.3.1 的结果是 B::f()

#14


已提交了值班室了,呵

#15


http://community.csdn.net/Expert/topic/3485/3485828.xml?temp=.7147486
虚基类层次的问题是把初始化共享虚资对象的职责转推到每个后续的派生类中。举例来说,我定义了一个基类,它的初始化需要分配一个缓冲区,用户指定的缓冲区的大小作为构造函数的一个参数传递。如果我实现了两个后续的虚继承,名字是inputb和outputb,每个都需要传递给基类构造函数一个特定的值。现在我定义一个派生自inputb和outputb两者的in_out类,那么两个本应传递给共享的基类子对象值都没有生效。

因此,在原始语言设计中,Stroustrup禁用了派生类构造函数的成员初始化类表中,虚基类成员的显式初始化。虽然这解决了这个问题,但是实际上无法控制虚基类,这被证明为是不可行的。国家健康研究所(译者:C++的普及可见一斑)的Keith Gorlen,一个叫做nihcl的免费版本SmallTalk集合库的实现者,是劝告Bjarne,让他必须考虑一个更灵活的语言设计的主要人员之一。

一个面向对象的层次设计的原则之一是一个派生类只应该涉及其本身和直接基类的非私有成员。为了支持一个灵活的虚继承设计,Bjarne 不得不破坏了这个原则。层次中最底层的类负责初始化所有虚对象,不管他们在层次中是哪一级。例如,inputb和outputb都有责任显式初始化他们的直虚接基类。在从inputb 和outputb派生in_out类的时候,in_out开始有责任进行一度被移除的虚基类初始化,并且inputb和outputb中的显式初始化被抑制了。

这提供了语言开发者需要的灵活性,但是以语义的复杂化为代价。如果我们限定虚基类必须没有状态,并且只允许指定一个接口,那么这个负担就被去掉了。这在C++中是一个推荐的设计方案。在C++/CLI中,这是Interface类型的方针。

去看看五星级人物的回答,反正我看了等于白看,就是说这一点由语言?(或编译器)开发者灵活掌握????