LNK1169 C++ 错误 类

LNK1169 Error C++ with own classes

刚刚注册,因为这个愚蠢的错误让我心烦意乱。

我用 1 个源文件中的所有内容以一种快速而肮脏的方式计算椭圆曲线。 然后我想清理我的代码并开始将函数和 类 分开在不同的文件中。 我用 C++ 编程已经有很长时间了,所以我想这是一个非常愚蠢的初学者错误。

所以我遇到了 LNK1169-Error 和 LNK2005-Error,我找到的解决方案是关于包含 .cpp,但我没有这样做。我虽然发现了 extern-keyword,但这似乎是全局变量的一种解决方案。

也许有人可以帮助我。

编辑: 抱歉放了那么多代码。我只是不知道什么与错误相关,什么不相关。

我得到的错误是这样的:

fatal error LNK1169: one or more multiply defined symbols found. Elliptic 1 C:\Users\Björn\documents\visual studio 2015\Projects\Elliptic 1\Debug\Elliptic 1.exe
error   LNK2005 "public: int __thiscall Value::operator==(class Value const &)" (??8Value@@QAEHABV0@@Z) already defined in Tests.obj
error   LNK2005 "public: int __thiscall Value::operator==(int)" (??8Value@@QAEHH@Z) already defined in Tests.obj

这是我的代码:

Value.hpp

#pragma once

extern int PRIME;

// An own Int-Class to overload operators with modulo
class Value
{
public:
    int v;
    static friend std::ostream& operator<<(std::ostream& os, const Value& a);

    Value()
    {
        this->v = 0;
    }
    Value(int a)
    {
        this->v = a;
    }
    Value operator+(const Value& other)
    {
        return Value((this->v + other.v) % PRIME);
    }
    Value operator+(int a)
    {
        return Value((this->v + a) % PRIME);
    }
    Value operator-(const Value& other)
    {
        Value t = Value((v - other.v) % PRIME);
        if (t.v < 0)
        {
            t = t + PRIME;
            return t;
        }
        return t;
    }
    Value operator-(int a)
    {
        Value t = Value((v - a) % PRIME);
        if (t.v < 0)
        {
            t = t + PRIME;
            return t;
        }
        return t;
    }
    void operator=(const Value other)
    {
        this->v = other.v;
    }
    Value operator*(const Value& a);
    Value operator*(int a);
    Value operator^(int a);
    Value operator/(const Value& a);
    int operator!=(int b);
    int operator!=(const Value& b);
    int operator==(int b);
    int operator==(const Value& b);
    Value operator~();
};

Value Value::operator*(const Value& a)
{
    return Value((this->v*a.v) % PRIME);
}
Value Value::operator*(int a)
{
    return Value((this->v*a) % PRIME);
}
Value Value::operator^(int b)
{
    Value ret(1);
    Value mul(this->v);
    while (b)
    {
        if (b & 1)
            ret = (ret * mul);
        b = (b >> 1);
        mul = mul * mul;
    }
    return ret;
}
Value Value::operator/(const Value& a)
{
    if (a.v == 0)
        return Value(0);
    Value f = (Value)a ^ (PRIME - 2);
    return *this * f;
}
int Value::operator!=(int b)
{
    if (this->v != b)
        return 1;
    return 0;
}
int Value::operator!=(const Value& b)
{
    if (this->v != b.v)
        return 1;
    return 0;
}
int Value::operator==(int b)
{
    if (this->v == b)
        return 1;
    return 0;
}
int Value::operator==(const Value& b)
{
    if (this->v == b.v)
        return 1;
    return 0;
}
Value Value::operator~()
{
    return *this ^ ((PRIME - 1 + 2) / 4);
}
std::ostream& operator<<(std::ostream& os, const Value& a)
{
    return os << a.v;
}

Point.hpp

#pragma once
#include "Value.hpp"
#include <iostream>

class Point
{

public:
    Value x;
    Value y;
    Value z = 0;

    static friend std::ostream& operator<<(std::ostream& os, const Point& p);

    Point(int a, int b)
    {
        x.v = a;
        y.v = b;
    }
    Point(int a, int b, int c)
    {
        x.v = a;
        y.v = b;
        z.v = c;
    }
    Point(Value a, Value b)
    {
        x.v = a.v;
        y.v = b.v;
    }
    Point(Value a, Value b, Value c)
    {
        x.v = a.v;
        y.v = b.v;
        z.v = c.v;
    }
    Point& operator=(const Point& other)
    {
        x.v = other.x.v;
        y.v = other.y.v;
        z.v = other.z.v;
        return *this;
    }
    int operator==(Point& other)
    {
        if (this->x == other.x && this->y == other.y && this->z == other.z)
            return 1;
        return 0;
    }
    int operator!=(Point& other)
    {
        if (this->x != other.x || this->y != other.y || this->z != other.z)
            return 1;
        return 0;
    }
};

std::ostream& operator<<(std::ostream& os, const Point& p)
{
    if ((Value)p.z == 0)
        return os << "(" << p.x.v << "," << p.y.v << ")";
    else
        return os << "(" << p.x.v << "," << p.y.v << "," << p.z.v << ")";
}

Helper.hpp

#pragma once
#include "Point.hpp"
#include <vector>

// Forward declaration
int isEC(Value a, Value b);
Value calcEC(int x, Value a, Value b);
int testSqr(Value ySqr);

// Point Addition
Point add(Point p1, Point p2, Value a)
{
    // 2D Addition
    if (p1.z == 0 && p2.z == 0)
    {
        // 2 different points
        if (p1.x.v != p2.x.v || p1.y.v != p2.y.v)
        {
            // m = (y2-y1)/(x2-x1)
            Value h = p2.y - p1.y;
            Value j = p2.x - p1.x;
            Value m = h / j;

            // x3 = m^2-x1-x2
            Value f = m*m;
            Value g = f - p1.x;
            Value x3 = g - p2.x;

            // y3 = m(x1-x3)-y1
            Value t = p1.x - x3;
            Value l = m * t;
            Value y3 = l - p1.y;

            if (x3.v < 0)
                x3 = x3 + PRIME;
            if (y3.v < 0)
                y3 = y3 + PRIME;

            return Point(x3, y3);
        }
        // Same points
        else
        {
            // m = (3*x1^2+a)/(2*y1)
            Value f = p1.x ^ 2;
            Value g = f * 3;
            Value h = g + a;
            Value j = p1.y * 2;
            Value m = h / j;

            // x3 = m^2-2*x1
            Value t = m*m;
            Value x = p1.x * 2;
            Value x3 = t - x;

            // y3 = m(x1-x3)-y1
            Value z = p1.x - x3;
            Value i = m * z;
            Value y3 = i - p1.y;

            if (x3.v < 0)
                x3 = x3 + PRIME;
            if (y3.v < 0)
                y3 = y3 + PRIME;

            return Point(x3, y3);
        }
    }
    // 3D Addition - Same points
    else if (p1 == p2 && p1.z == 1 && p2.z == 1)
    {
        Value A = p1.y ^ 2;
        Value B = p1.x * A * 4;
        Value C = (A ^ 2) * 8;
        Value D = (p1.x ^ 2)* 3 + a*(p1.z ^ 4);

        //Value x3 = (((3 * (p1.x ^ 2) + a*(p1.z ^ 4)) ^ 2) - 8 * p1.x*(p1.y ^ 2));
        Value x3 = (D ^ 2) - B * 2;

        //Value y3 = (3 * (p1.x ^ 2) + a*(p1.z ^ 4)*(4 * p1.x*(p1.y ^ 2) - x3) - 8 * (p1.y ^ 4));
        Value y3 = D*(B - x3) - C;

        Value z3 = p1.y*p1.z * 2;

        return Point(x3, y3, z3);
    }
    // 3D Addition - 2 different points
    else if (p1 != p2)
    {
        Value A = p1.z ^ 2;
        Value B = p1.z * A;
        Value C = p2.x * A;
        Value D = p2.y * B;
        Value E = C - p1.x;
        Value F = D - p1.y;
        Value G = E ^ 2;
        Value H = G * E;
        Value I = p1.x * G;

        Value x3 = (F ^ 2) - (H + (I * 2));

        Value y3 = F*(I - x3) - p1.y*H;

        Value z3 = p1.z * E;

        return Point(x3, y3, z3);
    }
    return Point(0, 0, 0);
}

// Find all points and print them
std::vector<Point> findAllPoints(Value a, Value b)
{
    Value ySqr;
    std::vector<Point> vec;

    std::cout << "Alle Punkte fuer a = " << a << ", b = " << b << " und Prime = " << PRIME << std::endl;

    // Is it an elliptic curve?
    if (isEC(a, b))
    {
        // Test all x-Values
        for (int x = 0; x <= PRIME - 1;x++)
        {
            // y^2
            ySqr = calcEC(x, a, b);

            // Test ySqr for square by root
            if (testSqr(ySqr))
            {
                //sqrt operator ~
                Value yPos = ~ySqr;

                std::cout << "(" << x << "," << yPos << ")\t";

                Value yNeg = yPos - (yPos * 2);

                // Save found points into vector
                vec.push_back(Point(x, yPos));
                vec.push_back(Point(x, yNeg));

                if (yNeg != 0)
                    std::cout << "(" << x << "," << yNeg << ")\t";
            }
        }
        //vec.insert(vec.begin(), Point(INFINITY, INFINITY));
        std::cout << std::endl;
    }
    else
        // Not an ellpitic curve
        std::cout << "\na and b are not leading to an ellptic curve.";

    return vec;
}

// Test if a and b lead to an EC
int isEC(Value a, Value b)
{
    if ((a ^ 3) * 4 + (b ^ 2) * 27 != 0)
        return 1;
    return 0;
}

// Calculate y^2
Value calcEC(int x, Value a, Value b)
{
    return Value(a*x + (x ^ 3) + b);
}

//  Test ySqr for square by root
int testSqr(Value ySqr)
{
    if ((ySqr ^ ((PRIME - 1) / 2)) == 1 || ySqr == 0)
        return 1;
    return 0;
}

Tests.hpp

#pragma once
#include "Helper.hpp"

class Tests
{
public:
    void twoDAdd(Value a, Value b);
    void twoDDoubling(Value a, Value b);
    void threeDAdd(Value a, Value b);
    void threeDDoubling(Value a, Value b);
};

Tests.cpp

#pragma once
#include <stdlib.h>
#include <vector>
#include <iostream>
#include <math.h>
#include <time.h>
#include "Tests.hpp"

// 2D - Addition
void Tests::twoDAdd(Value a, Value b)
{
    std::cout << "\n========== 2D Addition ==========\n";
    Point p2D1 = Point(5, 22);
    Point p2D2 = Point(16, 27);
    std::cout << p2D1 << " + " << p2D2 << " = " << add(p2D1, p2D2, a);
    std::cout << std::endl;
}

// 2D - Doubling
void Tests::twoDDoubling(Value a, Value b)
{
    std::cout << "\n========== 2D Doubling ==========\n";
    Point p2D1 = Point(5, 22);
    std::cout << "2 * " << p2D1 << " = " << add(p2D1, p2D1, a);
    std::cout << std::endl << std::endl;
}

// 3D - Addition
void Tests::threeDAdd(Value a, Value b)
{
    std::cout << "\n========== 3D Addition ==========\n";
    std::cout << "All points for a = " << a << ", b = " << b << " and prime = " << PRIME << std::endl;
    std::vector<Point> allPoints = findAllPoints(a, b);

    std::srand(time(NULL));
    int random = std::rand() % (allPoints.capacity() - 1);
    Point tmp = allPoints.at(random);
    std::cout << std::endl << "Random Point 1: " << tmp << std::endl << std::endl;

    tmp.z = 1;
    Point p1 = add(tmp, tmp, a);
    std::cout << p1 << std::endl;

    random = std::rand() % (allPoints.capacity() - 1);
    tmp = allPoints.at(random);
    std::cout << std::endl << "Random Point 2: " << tmp << std::endl << std::endl;

    tmp.z = 1;
    Point p2 = add(tmp, tmp, a);
    std::cout << p2 << std::endl;

    Point p3 = add(p1, p2, a);
    std::cout << p3 << std::endl;
}

// 3D - Doubling
void Tests::threeDDoubling(Value a, Value b)
{
    std::cout << "\n========== 3D Doubling ==========\n";
    std::cout << "All points for a = " << a << ", b = " << b << " and prime = " << PRIME << std::endl;
    std::vector<Point> allPoints = findAllPoints(a, b);

    int random = std::rand() % (allPoints.capacity() - 1);

    Point tmp = allPoints[random];
    std::cout << std::endl << "Random Point: " << tmp << std::endl << std::endl;

    Point p1 = add(tmp, tmp, a);
    std::cout << p1 << std::endl;

    tmp.z = 1;
    Point p2 = add(tmp, tmp, a);
    std::cout << p2 << std::endl;

    Point p3 = Point(p2.x / (p2.z ^ 2), p2.y / (p2.z ^ 3));
    std::cout << p3 << std::endl;

    if (p1 == p3)
        std::cout << "Point p1 == Point p3" << std::endl;
    else
        std::cout << "Point p1 != Point p3" << std::endl;
}

Main.cpp

#pragma once
#include <stdlib.h>
#include <vector>
#include <iostream>
#include <math.h>
#include <time.h>
#include "Tests.hpp"

int PRIME = 29;

void main()
{/*
    Value a = 4;
    Value b = 20;

    std::vector<Point> allPoints = findAllPoints(a, b);
    /*
    // Tests ausfuehren
    twoDAdd(a, b);
    twoDDoubling(a, b);
    threeDAdd(a, b);
    threeDDoubling(a, b);
    */
    std::cout << std::endl;
    system("pause");
}

在此先感谢,请原谅我的 "inperfect" 编码方式。

发生这种情况是因为您在头文件中定义了函数。我们将导入您的头文件的每个文件都将具有主体函数 - 这就是您出现此错误的原因。如果你想在头文件中有定义,你必须使用 inline 关键字。否则,您需要在 .cpp 文件中实现它们(解决此问题的 "correct" 方法)。

例如

// Test if a and b lead to an EC
inline int isEC(Value a, Value b)
{
    if ((a ^ 3) * 4 + (b ^ 2) * 27 != 0)
        return 1;
    return 0;
}

// Calculate y^2
inline Value calcEC(int x, Value a, Value b)
{
    return Value(a*x + (x ^ 3) + b);
}
//  Test ySqr for square by root
inline int testSqr(Value ySqr)
{
    if ((ySqr ^ ((PRIME - 1) / 2)) == 1 || ySqr == 0)
        return 1;
    return 0;
}