Глобальная инициализация const и разница между конструктором в файле .h или .cpp - PullRequest
0 голосов
/ 09 декабря 2010

Мне было интересно, почему иногда мой глобальный констант, определенный в отдельном файле .h, не инициализируется должным образом, когда мне это нужно.Некоторые тесты приводят меня к ситуации, которую я не могу понять.Я не знаю, как это объяснить, поэтому вот код:

main.cpp

#include <iostream>
#include "class.h"
using namespace std;

A a;
B b;

int main(int argc, char* argv[]){
A aa;
B bb;
cout<<a.a<<" "<<aa.a<<endl;
cout<<b.b<<" "<<bb.b<<endl;
return 0;
}

class.h

#ifndef CLASS_H
#define CLASS_H
#include "const.h"

class A {
public:
A();
float a;
};

class B {
public:
B():b(CONST){}
float b;
};
#endif

class.cpp

#include "class.h"
A::A()
: a(CONST){}

const.h

#ifndef CONST_H
#define CONST_H
#include <limits>
using namespace std;

const float CONST = numeric_limits<float>::has_infinity ? 
        -numeric_limits<float>::infinity() : 
        -numeric_limits<float>::max();
#endif

После выполнения кода выше я получаю:

0 -1. # INF
-1. # INF -1. # INF

, когда на самом деле я хотел бы получить 4 раза '-1. # INF'.Почему так происходит?Если бы CONST был '1' вместо приведенной выше формулы, он работал бы отлично.

Я могу "исправить" это, сделав статический метод getConst ():

static float getConst(){
static const float CONST = numeric_limits<float>::has_infinity ? 
        -numeric_limits<float>::infinity() : 
        -numeric_limits<float>::max();
return CONST;}

, но это простоне "чувствовать" правильно.С другой стороны, мне просто нужны два из вышеперечисленных ... Но, может быть, есть какой-то другой способ?

И, самое главное, почему класс B получает "правильный" CONST, а класс A - нет?

Ответы [ 4 ]

3 голосов
/ 09 декабря 2010

Порядок инициализации глобального объекта в разных единицах перевода не гарантируется.

Пожалуйста, посмотрите на этот вопрос:

1 голос
/ 09 декабря 2010

Постоянные объекты имеют внутреннюю связь, поэтому вы получаете отдельную копию CONST в каждой единице компиляции, которая включает const.h.В этом случае вы получите один в main.cpp и один в class.cpp.У вас также есть два глобальных объекта в main.cpp.

C ++ не определяет порядок инициализации глобальных объектов в разных единицах компиляции.Конструктор A s вызывается из main.cpp и нуждается в глобальной константе из class.cpp, которая еще не может быть инициализирована.В вашем конкретном случае этого не произошло, поэтому вы получаете неверное значение, которое видели.Конструктор B является встроенным, поэтому он использует глобальную константу из main.cpp, которая была инициализирована, поскольку она была определена ранее в том же модуле компиляции.теперь он гарантированно инициализируется при первом вызове этой функции.

0 голосов
/ 09 декабря 2010

Если я правильно понимаю ваш вопрос, то считаю, что проблема в том, что порядок инициализации любых глобальных объектов не определен.

0 голосов
/ 09 декабря 2010

Я нигде не вижу содержимого const.h, поэтому могу только догадываться, что такое CONST (макрос?).

Кроме этого, в вашем примере кода переменная-член A::a не инициализируется.Следовательно, он может иметь любое значение - он неинициализирован.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...