Вы можете попробовать использовать getuseravailability, который, если он будет работать, будет самым эффективным способом для многих пользователей, см. TimeZone и Рабочие часы для пользователей через EWS . Или попробуйте что-нибудь подобное http://gsexdev.blogspot.com.au/2015/11/finding-timezone-being-used-in-mailbox.html
Препроцессор - это программа, которая принимает вашу программу, вносит некоторые изменения (например, включают файлы (#include), расширение макроса (#define) и в основном все, что начинается с #
) и дает «чистый» результат к компилятору.
Препроцессор работает так, когда видит #include
:
Когда вы пишете:
#include "some_file"
Содержимое some_file
почти буквально получить копию, вставленную в файл, включая его. Теперь, если у вас есть:
a.h:
class A { int a; };
И:
b.h:
#include "a.h"
class B { int b; };
И:
main.cpp:
#include "a.h"
#include "b.h"
Вы получаете:
main.cpp:
class A { int a; }; // From #include "a.h"
class A { int a; }; // From #include "b.h"
class B { int b; }; // From #include "b.h"
Теперь вы можете увидеть, как переопределяется A
.
Когда вы пишете охранники, они становятся такими:
a.h:
#ifndef A_H
#define A_H
class A { int a; };
#endif
b.h:
#ifndef B_H
#define B_H
#include "a.h"
class B { int b; };
#endif
Итак, теперь давайте посмотрим, как #include
s в главном будет расширяться (это точно так же, как в предыдущем случае: copy-paste)
main.cpp:
// From #include "a.h"
#ifndef A_H
#define A_H
class A { int a; };
#endif
// From #include "b.h"
#ifndef B_H
#define B_H
#ifndef A_H // From
#define A_H // #include "a.h"
class A { int a; }; // inside
#endif // "b.h"
class B { int b; };
#endif
Теперь давайте следовать препроцессору и посмотреть, что из этого происходит «настоящий» код. Я пойду по строчке:
// From #include "a.h"
Комментарий. Игнорировать! Продолжить:
#ifndef A_H
Определен ли A_H
? Нет! Затем продолжаем:
#define A_H
Хорошо теперь A_H
. Продолжить:
class A { int a; };
Это не что-то для препроцессора, так что просто оставьте это. Продолжить:
#endif
Предыдущая if
завершена здесь. Продолжить:
// From #include "b.h"
Комментарий. Игнорировать! Продолжить:
#ifndef B_H
Определен ли B_H
? Нет! Затем продолжайте:
#define B_H
Хорошо теперь B_H
. Продолжить:
#ifndef A_H // From
Определен ли A_H
? ДА! Затем проигнорируйте до соответствующего #endif
:
#define A_H // #include "a.h"
Игнорировать
class A { int a; }; // inside
Игнорировать
#endif // "b.h"
Предыдущая if
завершена здесь. Продолжить:
class B { int b; };
Это не что-то для препроцессора, так что просто оставьте это. Продолжить:
#endif
. Предыдущая if
завершена здесь.
То есть, после того, как препроцессор сделан с файлом, это то, что видит компилятор:
main.cpp
class A { int a; };
class B { int b; };
Итак, как вы можете видеть, все, что может получить #include
d в том же файле дважды, прямо или косвенно, нужно охранять. Поскольку файлы .h
всегда очень часто включаются дважды, хорошо, если вы охраняете ВСЕ ваши .h-файлы.
P.S. Обратите внимание, что у вас также есть круговой #include
s. Представьте, что препроцессор скопировал код Physics.h в GameObject.h, который видит, что есть #include "GameObject.h"
, что означает копирование GameObject.h
в себя. Когда вы копируете, вы снова получаете #include "Pysics.h"
, и вы навсегда застреваете в цикле. Компиляторы предотвращают это, но это означает, что ваши #include
s наполовину сделаны.
Прежде чем говорить, как исправить это, вы должны знать другое.
Если у вас есть:
#include "b.h"
class A
{
B b;
};
Тогда компилятор должен знать все о b
, самое главное, какие переменные он имеет и т. д., чтобы он знал, сколько байтов должно помещать вместо b
в A
.
Однако, если у вас есть:
class A
{
B *b;
};
Тогда компилятору действительно не нужно ничего знать о B
(поскольку указатели, независимо от типа, имеют одинаковый размер ). Единственное, что ему нужно знать о B
, это то, что он существует!
Итак, вы делаете что-то под названием «forward declaration»:
class B; // This line just says B exists
class A
{
B *b;
};
Это очень похоже на многие другие вещи, которые вы делаете в заголовочных файлах, таких как:
int function(int x); // This is forward declaration
class A
{
public:
void do_something(); // This is forward declaration
}
Добавить включить охранники во все ваши файлы заголовков *.h
или *.hh
(если у вас нет особых причин не делать этого).
Чтобы понять, что происходит, попробуйте получить предварительно обработанную форму ваш исходный код. С GCC это нечто вроде g++ -Wall -C -E yourcode.cc > yourcode.i
(я не знаю, как это делают компиляторы Microsoft). Вы также можете спросить, какие файлы включены, с GCC как g++ -Wall -H -c yourcode.cc
Проблема в том, что ваш GameObject.h
не имеет охранников, поэтому, когда вы #include "GameObject.h"
в Physics.h
, он включается, когда GameObject.h
включает Physics.h
.
У вас есть круглые ссылки здесь: Physics.h
включает GameObject.h
, который включает Physics.h
. Ваш класс Physics
использует тип GameObject*
(указатель), поэтому вам не нужно включать GameObject.h
в Physics.h
, но просто используйте форвардное объявление - вместо
#include "GameObject.h"
put
class GameObject;
Кроме того, поместите защитные устройства в каждый файл заголовка.
Во-первых, вам также нужно включить охранников в игровой объект, но это не настоящая проблема здесь.
Если что-то еще включает в себя физику.h сначала, в физике.h есть gameobject.h, вы получите что-то вроде этого:
class GameObject {
...
};
#include physics.h
class Physics {
...
};
и #include Physics.h отбрасывается из-за включенных охранников, и вы получаете объявление GameObject до объявления физики.
Но это проблема если вы хотите, чтобы GameObject имел указатель на физику, потому что для физики htat нужно было бы объявить сначала.
Чтобы разрешить цикл, вы можете переслать-объявить класс вместо этого, но только если вы просто используя его как указатель или ссылку в следующем объявлении, то есть:
#ifndef PHYSICS_H
#define PHYSICS_H
// no need for this now #include "GameObject.h"
#include <list>
class GameObject;
class Physics
{
private:
list<GameObject*> objects;
list<GameObject*>::iterator i;
public:
void ApplyPhysics(GameObject*);
Vector2X CheckCollisions(Vector2X, GameObject*);
};
#endif // PHYSICS_H
Используйте ВСЕ охранные файлы во всех файлах заголовка. Поскольку вы используете Visual Studio, вы можете использовать #pragma once
в качестве первого определения препроцессора во всех ваших заголовках.
Однако я предлагаю использовать классический подход:
#ifndef CLASS_NAME_H_
#define CLASS_NAME_H_
// Header code here
#endif //CLASS_NAME_H_
Second прочитайте о forward declaration и примените его.