编译能通过吗?靠!
public class Y: public X{}???????什么写法?
结果应该是
X::foo()
X::foo()
因为foo()在X的构造函数里面调用,此时Y还没有构造,所以所有虚函数指针是指像X里面的函数的

解决方案 »

  1.   

     Kevin_qing(Kevin) 兄,首先申明我只是就我的认识来回答这个问题,没有具体去试过,所以,如果有不对的地方请指正:
    我觉得这个问题主要牵涉到c++的继承的问题。
    我认为结果应该是:
    Y::foo
    X::foo
    赫赫,是吗?因为在构建class Y的对象的时候,编译器寻找class Y的构造函数,找不到,所以向上查找起伏类的构造函数,即调用class X的构造函数,同样的道理,调用foo(),所以print出Y::foo,然后调用bar()方法,由于当前类没有实现所以利用父类的bar()方法,所以print 出X::foo,
    ok?
      

  2.   

    sorry. 正确的程序是这样的#include <stdio.h>
    class X
    {
    public:
    X() {
    foo();
    bar(); 
    }void bar() {
    foo(); 
    }virtual void foo() {
    printf("X::foo\n");
    }
    };class Y: public X
    {
    public:
    virtual void foo() {
    printf("Y::foo\n");
    }
    };void main()
    {
    new Y(); 
    }
      

  3.   

    请关注下面的帖子:
    http://codeguru.earthweb.com/cgi-bin/bbs/wt/showpost.pl?Board=CSharp&Number=939&page=0&view=collapsed&sb=5
      

  4.   


    1. baseclass constructor( )
    2. copy vfptr
    (beging ur code)
    3.early binding callees
      

  5.   

    answer:
         X:foo()
         X:foo()
         Y:foo()
      

  6.   

    X:foo()
    X:foo()
    构造函数中是编译绑定。
      

  7.   

    好象在CLASS定义的后面应该加上;吧,不然编译怎么能通过呢?别的我就没看了,哈哈。:-)
      

  8.   

    编译出来,运行结果是:
    X:foo
    X:foo
    原因与Kevin_qing(Kevin)观点相同。
        
      

  9.   

    有人用gcc编译执行过吗,还有java平台,C#平台.欢迎提供测试结果!
      

  10.   

    有人用gcc编译执行过吗,还有java平台,C#平台.欢迎提供测试结果!
      

  11.   

    X::foo
    X::foo
    这是很明显的啊,new Y()要调用本身和父类的构造函数,而其父类的
    X() {
    foo();
    bar(); 
    }
    就是prinft两次x::foo啊。还有,你程序中声明的虚函数没必要吧?
      

  12.   

    答案是:
    x::foo()
    x::foo()
    类y中无构造函数。
    所以向上查找。从而得出以上结果
      

  13.   

    确实象C++
    结果好象应该和楼上的几位兄台说的是::foo
    不过,我个人觉得好象是:
    Y::foo
    Y::foo
    没有调试过,不知正确否
    hoho
      

  14.   

    很少到vc论谈,感觉是高手如云,这问题最基本的C++书上都有,不知怎么成为热门话题
    classq 前加public也就算了,c++在java平台是什么时候可以编译的?java中能有不属于
    任何类的main方法吗?实在是不懂
      

  15.   

    没有调试过,不过肯定是
    X:foo
    X:foo
    实际上涉及到了虚构造函数的概念,在生成基类的时候,子类还没有生成,所以虚机制根本还没有起作用
      

  16.   

    完全赞同newpeak(),
    结果是肯定的,要真的不相信的话,
    我在VC++6上编译过了,
    --------------------Configuration: testvirtul - Win32 Debug--------------------
    Compiling...
    testvirtual.cpp
    Linking...testvirtual.exe - 0 error(s), 0 warning(s)输出为:
    X::foo
    X::foo
    Press any key to continue
      

  17.   

    调试过,不过肯定是
    X:foo
    X:foo
      

  18.   

       大家可能有点误会,我的本意是想和大家探讨:虚函数在构造函数中被调用的机制。
       至于java, C#,C++中的不同写法我想大家都很明白,不必要全部要我写出来吧。
       其实下面的帖子更加详细,相信大家能明白我的本意。---http://codeguru.earthweb.com/cgi-bin/bbs/wt/showpost.pl?Board=CSharp&Number=939&page=0&view=collapsed&sb=5 
      

  19.   

    我没学过C++,只学过JAVA。用JAVA的思想来解答这道题,答案应该是:
    X::foo
    X::foo
    因为Class Y中并没有自己的构造函数,但它继承了Class X,所以语句new Y()实际上就是调用Class X的构造函数---X()。 
      

  20.   

    首先,正确的写法如下:
    #include <stdio.h>class X
    {
    public:
    X() 
    {
    foo();
    bar(); 
    }

    void bar() 
    {
    foo(); 
    } virtual void foo() 
    {
    printf("X::foo\n");
    }
    };class Y: public X
    {
    public:
    virtual void foo() 
    {
    printf("Y::foo\n");
    }
    };void main()
    {
    new Y(); 
    }结果应该是:
    X::foo
    X::foo
    类构造时首先调用基类的构造函数然后再调用自己的构造函数
    由于是虚函数,所以函数指针会指向正确的类(在此是基类X)
    你可以给类Y加同样的构造函数如:
    X() 
    {
    foo();
    bar(); 
    }
    然后再运行你就明白了
    还可以去掉virtual关键字试一下
      

  21.   

    照大家这样说的话,那么下面的虚函数InitInstance()就执行不了,则这个标准的MFC程序不就有问题了吗?(下面的程序也和上面的类似)
     //hello.cpp
     #include <afxwin.h>
     class CHelloApp : public CWinApp
     { public:
     virtual BOOL InitInstance();
     };
     CHelloApp HelloApp;
     class CHelloWindow : public CFrameWnd
     { 
     CStatic* cs;
     public:
     CHelloWindow();
     };
     BOOL CHelloApp::InitInstance()
     {
     m_pMainWnd = new CHelloWindow();
     m_pMainWnd->ShowWindow(m_nCmdShow);
     m_pMainWnd->UpdateWindow();
     return TRUE;
     }
     CHelloWindow::CHelloWindow()
     { 
     Create(NULL, "Hello World!", WS_OVERLAPPEDWINDOW, CRect(0,0,200,200));
     cs = new CStatic();
     cs->Create("hello world", WS_CHILD|WS_VISIBLE|SS_CENTER, CRect(50,80,150,150),this);
     }
      

  22.   

    to zqshan:
       InitInstance()是在AfxWinMain(MFC的WinMain人口)里被直接调用的,而不是在CWinApp的构造函数中。
      

  23.   

    这个问题确实很有意思,它远比我们想当然的认为要复杂的多
    在Y的构造函数中,因为我们没有给出自己定义的default ctor,而Y又是从一个有着default ctor的class X中继承下来的。所以C++会为我们产生一个Y的default ctor,它的实现只是C++为了满足自己的编译条件。对于父类有default ctor的情况下,生成的default ctor的代码是先调用父类的default ctor(父类的ctor肯定要被调用,有时可以显式的调用-通过initialize list,有时为隐式调用,如我们现在讨论的情况),如果类中还含有带有default ctor的member的话,则生成的default ctor还将调用这些member的default ctor(在父类的之后,如果有多个这样的member,则它们的default ctor调用顺序以它们的宣告顺序一样)。
    一个类的构造函数的大致流程为,先分配容纳该对象的内存给它,然后再配置这块内存,即在它上面调用构造代码
    如果有virtual的话则生成其vtbl(如果有上面说的情况,则先生成父类及member对象(包括构造出它们自己的vtbl来)),
    然后调用我们写在ctor中的代码通过这种情况,我们就可以知道得到这样的输出是必然的了:)
    X::foo
    X::foo
      

  24.   

    不懂就去看  《深入浅出MFC》
    KAO!
    不难吧!
      

  25.   

    其实你写的这段代码根本谈不上是虚函数的调用机制的问题.这应该算是一个继承类对象创建时构造函数的调用顺序的问题.因为在构造y对象时,要先调用基类的构造函数,而基类的构造函数调用时肯定于从他继承下来的类y没关系!所以结果必然是:
    X::foo()
    X::foo()
    开始一看你的标题还真有点不自信了,不过从这道题我还是悟出了一个道理;那就是一定要自信;)
      

  26.   

    This behavior makes sense for two reasons. Conceptually, the constructor’s job is to bring the object into existence (which is hardly an ordinary feat). Inside any constructor, the object may only be partially formed – you can only know that the base-class objects have been initialized, but you cannot know which classes are inherited from you. A virtual function call, however, reaches “forward” or “outward” into the inheritance hierarchy. It calls a function in a derived class. If you could do this inside a constructor, you’d be calling a function that might manipulate members that hadn’t been initialized yet, a sure recipe for disaster.
    The second reason is a mechanical one. When a constructor is called, one of the first things it does is initialize its VPTR. However, it can only know that it is of the “current” type. The constructor code is completely ignorant of whether or not the object is in the base of another class. When the compiler generates code for that constructor, it generates code for a constructor of that class, not a base class and not a class derived from it (because a class can’t know who inherits it). So the VPTR it uses must be for the VTABLE of that class. The VPTR remains initialized to that VTABLE for the rest of the object’s lifetime unless this isn’t the last constructor call. If a more-derived constructor is called afterwards, that constructor sets the VPTR to its VTABLE, and so on, until the last constructor finishes. The state of the VPTR is determined by the constructor that is called last. This is another reason why the constructors are called in order from base to most-derived.只想说:中国程序员都TMD太牛X!!!
      

  27.   

    这个题目确实很难,稍不注意便会疏漏一些重要的东西。而且你只要将这个程序略微的修改一下,又可以发现很多有意思的情况(如用一个inline调用virtual,然后在ctor中调用这个inline)。
    希望大家在回答前先仔细的,全面的考虑清楚后再发言。
    我很赞同bgsn的话:“不是说真是水平有多高,而是不够谦虚严谨,骄傲自大!!!”