Я попытался создать структуру секундомера, цель которой - измерить время с помощью функции QueryPerformanceCounter(), и если она не существует или не поддерживается, она возвращается к использованию clock() в time.h ,Ошибка связывания статического поля
К сожалению, ошибка линкера происходит следующим образом:
Error LNK2001: unresolved external symbol "private: static struct Stopwatch::StopwatchInitializer Stopwatch::platformInfo" ([email protected]@@[email protected]@A) in Main.obj
При изменении platformInfo
в нестатическая, приложение работает, но если отмечен static
, это не так.
Мое намерение состоит в том, чтобы оставить его статическим, чтобы оно инициализировалось только один раз, но Linker не сотрудничает.
Почему? Вот мой код:
stdafx.h:
#pragma once
#include "time.h"
#ifdef _WIN32
#include "windows.h"
#endif
//A stopwatch function provider that offers clock tick accuracy
struct Stopwatch {
//holds the platform data required to initialize the stopwatch
private:
struct StopwatchInitializer {
public:
double nanosecondsPerTick;
bool isHighResolution;
StopwatchInitializer() {
#ifdef _WIN32
LARGE_INTEGER value;
isHighResolution = !!QueryPerformanceFrequency(&value);
nanosecondsPerTick = isHighResolution ? 1000000000.0/value.QuadPart : 1000000000.0/CLOCKS_PER_SEC;
#elif
isHighResolution = false;
nanosecondsPerTick = 1000000000.0/CLOCKS_PER_SEC;
#endif
}
};
//static single instance of the StopwatchInitializer instance
//here is the error though
static const StopwatchInitializer platformInfo;
double startTimeStamp, elapsed;
bool isRunning;
public:
//Initializes the stopwatch.
Stopwatch() {
elapsed = 0.0;
startTimeStamp = 0.0;
isRunning = false;
}
//Initializes the stopwatch with the specified pre-elapsed ticks.
Stopwatch(double preElapsedTicks) {
elapsed = preElapsedTicks;
startTimeStamp = 0.0;
isRunning = false;
}
//Gets the current time in platform-specific ticks.
double getTimeStamp() {
#ifdef _WIN32
if (platformInfo.isHighResolution) {
LARGE_INTEGER num;
QueryPerformanceCounter(&num);
return (double) num.QuadPart;
} else
return (double) clock();
#elif
return (double) clock();
#endif
}
//Starts or resumes the stopwatch.
void start() {
if (isRunning)
return;
isRunning = true;
startTimeStamp = getTimeStamp();
}
//Stops the stopwatch.
void stop() {
if (isRunning) {
isRunning = false;
elapsed += getTimeStamp() - startTimeStamp;
}
}
//Gets whether the stopwatch is running
int getIsRunning() {
return isRunning;
}
//Sets whether the stopwatch is running (boolean value).
void setIsRunning(bool value) {
if (value)
start();
else
stop();
}
//Gets the current elapsed ticks.
double getElapsedTicks() {
return isRunning ? (elapsed - startTimeStamp) + getTimeStamp() : elapsed;
}
//Gets the elapsed time in fortnights.
double getElapsedFortnights() {
return (platformInfo.nanosecondsPerTick * 0.00000000000000082671957671957672) * getElapsedTicks();
}
//Gets the elapsed time in weeks.
double getElapsedWeeks() {
return (platformInfo.nanosecondsPerTick * 0.00000000000000165343915343915344) * getElapsedTicks();
}
//Gets the elapsed time in days.
double getElapsedDays() {
return (platformInfo.nanosecondsPerTick * 0.00000000000001157407407407407407) * getElapsedTicks();
}
//Gets the elapsed time in hours.
double getElapsedHours() {
return (platformInfo.nanosecondsPerTick * 0.00000000000027777777777777777777) * getElapsedTicks();
}
//Gets the elapsed time in minutes.
double getElapsedMinutes() {
return (platformInfo.nanosecondsPerTick * 0.00000000001666666666666666666666) * getElapsedTicks();
}
//Gets the elapsed time in seconds.
double getElapsedSeconds() {
return (platformInfo.nanosecondsPerTick * 0.000000001) * getElapsedTicks();
}
//Gets the elapsed time in milliseconds.
double getElapsedMilliseconds() {
return (platformInfo.nanosecondsPerTick * 0.000001) * getElapsedTicks();
}
//Gets the elapsed time in microseconds.
double getElapsedMicroseconds() {
return (platformInfo.nanosecondsPerTick * 0.001) * getElapsedTicks();
}
//Gets the elapsed time in nanoseconds.
double getElapsedNanoseconds() {
return platformInfo.nanosecondsPerTick * getElapsedTicks();
}
//Resets the elapsed time.
void reset() {
elapsed = 0.0;
isRunning = false;
startTimeStamp = 0.0;
}
//Resets the elapsed time to the specified platform-specific ticks.
void reset(double ticks) {
elapsed = ticks;
isRunning = false;
startTimeStamp = 0.0;
}
//Resets the stopwatch and restarts it.
void restart() {
elapsed = 0.0;
isRunning = true;
startTimeStamp = getTimeStamp();
}
//Resets the stopwatch to specified platform-specific ticks and restarts it.
void restart(double ticks) {
elapsed = ticks;
isRunning = true;
startTimeStamp = getTimeStamp();
}
//Converts nanoseconds to platform-specific ticks.
double convertToTicks(double nanoseconds) {
return nanoseconds/platformInfo.nanosecondsPerTick;
}
//Converts platform-specific ticks to nanoseconds.
double convertToNanoseconds(double ticks) {
return ticks * platformInfo.nanosecondsPerTick;
}
};
main.h:
#include "stdafx.h"
#include "stdio.h"
//entry point
int main() {
Stopwatch stopwatch;
int x;
double value = 100002030.0;
stopwatch.start();
for (x = 0; x < 100000000; x++)
value /= 2.2;
printf("Division: %fms, value: %f", stopwatch.getElapsedMilliseconds(), value);
value = 100002030.0;
stopwatch.restart();
for (x = 0; x < 100000000; x++)
value *= 0.45454545454;
printf("\nMultiplication: %fms, value: %f", stopwatch.getElapsedMilliseconds(), value);
scanf_s("");
}
О, спасибо! Я не знал, что мне нужно повторно объявить частные статические константные поля. :) –
не только частные и const, [все статические] (http://stackoverflow.com/questions/3536372/defining-static-members-in-c) – yuyoyuppe
Приветствия, это полезно знать в будущем! –