c++ - 静态字段链接器错误

标签 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;
    }
};

主要.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("");
}

最佳答案

您声明了静态成员 platformInfo,但没有定义它,所以链接器会提示它。要在类之外定义此静态成员,请将此行添加到源代码的顶层:

const Stopwatch::StopwatchInitializer Stopwatch::platformInfo;

关于c++ - 静态字段链接器错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35717003/

相关文章:

c++ - 我可以在字符串中包含 vector 吗?

c++ - Visual Studio 2013 dll 导出链接错误 (LNK2019/LNK1120)

visual-studio-2010 - 在VS2010下的OpenCV 2.4.2中, Release模式下的运行时错误?

c++ - 多个子进程的 PID 从同一个父进程中 fork 出来

c++ - string.empty() 或 string.size() == 0 哪个更快?

java - 如何使用 GDB 从 native 调用调试到 java 函数?

c++ - g++ 链接目标文件无法链接

c++ - 数据结构 : I am getting undesired value

c++ - 重载在基类非虚函数中使用的虚函数

c++ - .cpp 文件中定义的 Constexpr 构造函数导致链接错误