定义了一个全局对象,如何保证他是第一个构造呢?放在theApp上面可以保证构造早于theApp,但是如果有很多文件呢,怎么保证要比其他文件中的全局变量构造早呢有人说和编译顺序有关,后编译的文件先构造,但是在实验中发现又不是这个样子,
请问,多个文件中的全局对象,构造顺序是如何的?

解决方案 »

  1.   

    全局对象就够早了,为什么要特别比其他早.可以所有全局对象都构建了,然后在InitInstance中坐各个对象初始化工作,这样就可以控制顺序了
      

  2.   

    typedef struct _tagMyStruct
    {
    } MyStruct;#define SECNAME ".CRT$XCB"
    #pragma section(SECNAME, long, read)__declspec(allocate(SECNAME)) MyStruct myStruct;
      

  3.   

    但是如果其他的文件里也是这样,那么不能保证了。
    这只能保证相对于缺省编译器的全局数据。
    如果你需要自定义的数据也后先后关系,那么在 SECNAME 上面做文档。
    会按照 SECNAME 的顺序构造。
    缺省的编译器可能在
    #pragma section(".CRT$XCC",long,read)
    #pragma section(".CRT$XCU",long,read)
    构造,具体好像是 VC 编译器有修改。
    但是 在 CC之前肯定可以在缺省数据之前构造。
      

  4.   

    多谢 oyljerry 能回复,有特殊的应用场合,并且不算不合理。比如有一个可以进程通信的日志记录类,他用来记录一个程序的所有启动日志(用于调试),包括记录程序实例创建之前其他的一切全局对象的初始化过程。这个时候是不是就要求它要第一个启动啊。
    当然,发现了这个问题,就可以绕过去,现在只是探讨一下如何实现。
      

  5.   

    对于不同文件中的全局对象、变量,它们的构造函数调用顺序是未定义的,取决于具体的编译器。
    最好不要写出和编译顺序相关的程序来。强烈建议楼主绕开这个问题,寻找代替方案。举例如下:
    int   a=5; 
    int   b=a; 
    如果a和b定义在同一个文件里,那没什么问题,结果b等于5. 
    如果a和b定义在不同文件里,当遇到b=a时不能保证a先初始化,解决这种问题的方法是不直接使用全局变量,而改用一个包装函数来访问。nt   get_a() 

              static   int   a   =   5; 
              return   a; 

    int   get_b() 

              static   int   b   =   get_a(); 
              return   b; 

       这样的话,无论get_a和get_b是否定义在同一个文件中,get_b总是 能够返回正确的结果,原因在于,函数内部的静态变量是在第一次访问的时候来初始化。
      

  6.   

    #pragma init_seg({ compiler | lib | user | "section-name" [, func-name]})
    可以设置优先初始化顺序。
      

  7.   

    我也没办法保证global对象的实例化顺序.我一般不喜欢对象构造里做实际工作.比如构造里就listen啥的.一般都是对象有个init开始做实际的工作.这样就不会担心global的顺序了.等main进入了后,把对象顺序init调用就行了.
      

  8.   

    那么你就记录不了main之前程序都干了什么。
      

  9.   

    main之前也可以写啊,你都设计成这样了,你还在乎main之前的东西?
      

  10.   

    你干嘛要记录main 之前干了什么?main之前干了什么你翻翻crt不就知道了,又不会变~
      

  11.   

    就像他们说的,可以写个init的函数,例如在你的类都调用之前对他们进行初始化。
      

  12.   

    这不能确定吧,况且全局对象本身就是不安全的··将所有全局对象 换成 全局指针, 在main中构造,顺序由你决定··
      

  13.   

    云空间-全面进入免费云时代-国内首家免费T级云空间!
    云空间为您提供的空间容量为1T,支持ASP,PHP,.NET等脚本。有独立的控制面板。支持绑域名等.云空间专业的在线云存储技术,分布式存储系统架构,让您无论何时何地都可快速访问你的网站 
    申请地址 :http://www.83432.com/free/
      

  14.   

    请参考这里
    http://msdn.microsoft.com/zh-cn/library/7977wcck.aspx
      

  15.   

    编译器是单独编译各个cpp文件的,然后再链接。至于链接时如何安排全局对象,没有听过介绍,可能是不确定的。
    如果你一定要保证某一个全局对象第一个构造,这样试试:定义一个文件Allobject.cpp,把所有的全局对象都放在这个文件中。
    当然你需要的对象放在最前。然后定义一个文件Allobject.h,在这里这样申明所有的全局对象:
    #ifndef ALLOBJECT
    #DEFINE ALLOBJECT
    extern string test1;
    extern int test2;
    .....
    #ENDIF然后在需要全局对象的cpp文件中,
    #include Allobject.h
      

  16.   


    saleayas 兄能解释一下吗,这段是什么意思啊?
    .CRT$XCB是关键字吗,是不是手动控制编译的代码段?
      

  17.   

    补充:我已经实现了不关心全局对象的构造顺序的程序。
    只是借机会讨论一下有没有预编译指令来定义全局对象的构造顺序,因为全局对象的编译和链接是有一定的规则的,满足了规则就能够实现了!
    不了解的请看下面网址,看懂的请告诉鄙人如何实现,多谢!

    http://blog.csdn.net/gao_zilai/article/details/7059600
      

  18.   


    // a.h
    #ifndef _A_H__
    #define _A_H__extern int nA;void setA(int a);#endif#endif// a.cpp
    #include "a.h"int nA; // int nA = 10;void setA(int a)
    {
       nA = a;
    }// main.cpp#include "a.h"
    #include <iostream>int main()
    {
    int b = nA;
    std::cout << b << std::endl; ::system("pause");
    return 0;
    }
    个人理解,作为一个全局对象,使用者必然会在对象定义的地方给对象赋予一个初值(如果你非要不给初值,);
    在调用全局对象的地方,必然会包含相关的头文件。相关的c,cpp文件的编译顺序会不一致,但是运行的时候,必然是所有c,cpp文件多编译并链接之后。所以我觉得没有必要保证全局对象就必须第一个构造,在全局对象定义的地方赋予初值即可。使用到该全局对象的地方是可以使用到已被赋予初值的全局对象。
      

  19.   

    #pragama init_seg 预处理器指令可以满足你的需要.
      

  20.   

    编译器在编译文件时,会把所有的数据放到指定的 SECTION 中。
    可以看看 init_seg 指令。
    这些 SECTION 按照其名字的字典顺序连续排列。
    而 VC编译器的缺省全局初始化数据在 .CRT$XCC 段中。
    那么如果你的数据的段的名称在 .CRT$XCC 之前就可以在缺省数据之前初始化。
    那么如果 设置 .CRT$XCB,那么该段在 .CRT$XCC 之前初始化。一般来说,我们在不同的 .CPP 文件中定义不同的相似的数据,同时又希望这些数据构成一个数组。
    那么此时我们把这些相似的数据放在指定的段中,编译器就会把它们连在一起。其中 .CRT$XCC 等等这样的数据,在连接后会放在 .CRT 中。
    VC 编译器会合并 $ 之前相同的名字。具体可以看看 ATL 的实现。
    或者看看 crt0.c 文件,在这个文件里你可以看到 C 语言是怎么调用 main 函数的,
    以及在 main 函数之前如何初始化全局变量的。
      

  21.   

    利用JQuery的$.ajax()可以很方便的调用asp.net的后台方法。
    先来个简单的实例热热身吧。
    1、无参数的方法调用
    asp.net code:
    using System.Web.Script.Services;
    [WebMethod]
    public static string SayHello()
    {
    return "Hello Ajax!";

    注意:1.方法一定要静态方法,而且要有[WebMethod]的声明
    JQuery code:
    /// <reference path="jquery-1.4.2-vsdoc.js"/>
    $(function() {
    $("#btnOK").click(function() {
    $.ajax({
    //要用post方式
    type: "Post",
    //方法所在页面和方法名
    url: "data.aspx/SayHello",
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    success: function(data) {
    //返回的数据用data.d获取内容
    alert(data.d);
    },
    error: function(err) {
    alert(err);
    }
    });
    //禁用按钮的提交
    return false;
    });
    }); 
    结果:
    2、带参数的方法调用
    asp.net code:
    using System.Web.Script.Services;
    [WebMethod]
    public static string GetStr(string str, string str2)
    {
    return str + str2;

    JQuery code:
    /// <reference path="jquery-1.4.2-vsdoc.js"/>
    $(function() {
    $("#btnOK").click(function() {
    $.ajax({
    type: "Post",
    url: "data.aspx/GetStr",
    //方法传参的写法一定要对,str为形参的名字,str2为第二个形参的名字
    data: "{'str':'我是','str2':'XXX'}",
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    success: function(data) {
    //返回的数据用data.d获取内容
    alert(data.d);
    },
    error: function(err) {
    alert(err);
    }
    });
    //禁用按钮的提交
    return false;
    });
    }); 
    运行结果:
     
    下面进入高级应用罗
    3、返回数组方法的调用
     asp.net code:
    using System.Web.Script.Services;
    [WebMethod]
    public static List<string> GetArray()
    {
    List<string> li = new List<string>();
    for (int i = 0; i < 10; i++)
    li.Add(i + "");
    return li;

    JQuery code:
     /// <reference path="jquery-1.4.2-vsdoc.js"/>
    $(function() {
    $("#btnOK").click(function() {
    $.ajax({
    type: "Post",
    url: "data.aspx/GetArray",
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    success: function(data) {
    //插入前先清空ul
    $("#list").html("");
    //递归获取数据
    $(data.d).each(function() {
    //插入结果到li里面
    $("#list").append("<li>" + this + "</li>");
    });
    alert(data.d);
    },
    error: function(err) {
    alert(err);
    }
    });
    //禁用按钮的提交
    return false;
    });
    }); 
    运行结果:
    4、返回Hashtable方法的调用
    asp.net code:
    using System.Web.Script.Services;
    using System.Collections;
    [WebMethod]
    public static Hashtable GetHash(string key,string value)
    {
    Hashtable hs = new Hashtable();
    hs.Add("www", "yahooooooo");
    hs.Add(key, value);return hs;

    JQuery code:
    /// <reference path="jquery-1.4.2-vsdoc.js"/>
    $(function() {
    $("#btnOK").click(function() {
    $.ajax({
    type: "Post",
    url: "data.aspx/GetHash",
    //记得加双引号 T_T
    data: "{ 'key': 'haha', 'value': '哈哈!' }",
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    success: function(data) {
    alert("key: haha ==> "+data.d["haha"]+"\n key: www ==> "+data.d["www"]);
    },
    error: function(err) {
    alert(err + "err");
    }
    });
    //禁用按钮的提交
    return false;
    });
    }); 
     运行结果:
     
     5、操作xml
      

  22.   

    多谢(网络小虫)和(Saleayas),给我指明了一条方向,抛砖引玉,继续讨论。微软说:
    In the Microsoft C++ Compiler, it is possible to control when your static objects, declared at file scope, are constructed and destructed by using the #pragama init_seg preprocessor directive. 
    ...
    The purpose of this directive is to give the developer the ability to group the constructors in an application. This would be useful if some objects relied upon the existence of other objects to function correctly.大概意思:
    在微软C++编译器中,你可以使用预编译指令"#pragama init_seg"去控制静态对象、全局对象的构造和析构。

    这条指令的目的是让开发人员能够组织一个应用程序的对象构造函数。这在一些对象依赖于其他对象的存在才能正确调用函数的时候非常有用。
      

  23.   


    搞什么飞机?! 搞web js的也来了. jquery