静态字段链接器错误

时间:2016-03-01 07:27:43

标签: c++ linker-errors

我尝试创建一个Stopwatch结构,其目的是使用Windows QueryPerformanceCounter()函数测量时间,如果它不存在或不受支持,它将回退到在time.h中使用clock()。

不幸的是,链接器错误发生如下:

Error LNK2001: unresolved external symbol "private: static struct Stopwatch::StopwatchInitializer Stopwatch::platformInfo" (?platformInfo@Stopwatch@@0UStopwatchInitializer@1@A) in Main.obj

当我将platformInfo更改为非静态时,该应用程序可以正常运行,但如果标记为static,则不会。

我的目的是让它保持静态,以便它只被初始化一次,但链接器没有合作。

为什么?这是我的代码:

的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("");
}

1 个答案:

答案 0 :(得分:1)

您声明了静态成员platformInfo,但没有定义它,因此链接器会抱怨它。要在类之外定义此静态成员,请在源的顶级添加此行:

const Stopwatch::StopwatchInitializer Stopwatch::platformInfo;