Как включить глобально определенные константы в библиотеку C++?

1
9

Я буду использовать конкретный, хотя и упрощенный, пример, чтобы проиллюстрировать, что я имею в виду. Предположим, мы разрабатываем библиотеку, связанную с комплексными числами. Мы определяем два класса: "cmplx", который представляет комплексные числа, и "meta", который является некоторым классом, который использует "cmplx" для определения своих членов. Мы хотим предоставить 3 константных экземпляра этих классов: "cmplx0", "cmplxi" и "meta0". Как вы увидите, когда я представлю code, cmplx0 = 0+0*i, cmplxi = 0+i, а meta — это просто какая-то ерунда, которую я придумал, чтобы донести свою точку зрения. Суть в том, что каждая из этих переменных представляет собой определенный экземпляр математического объекта, мы хотим, чтобы пользователь мог использовать их примерно так же, как он использовал бы "1" или "M_PI". Проблема в том, что я постоянно получаю ошибки компоновки при попытке компиляции.

Я ссылался на этот вопрос, но безуспешно. Я привел пример ниже, когда я его запускаю, я получаю "error: ld returns status 1". Я использую VS Code и g++ на Windows 10. Структура каталогов выглядит так:

\headers

\headers\cmplx.h

\headers\meta.h

\sources

\sources\cmplx.cpp

\sources\meta.cpp

\examples

\examples\test.cpp

\lib.h

\makefile

cmplx.h

meta.h

cmplx.cpp

meta.cpp

test.cpp

lib.h

makefile

Я был бы признателен любые отзывы, которые вы можете мне дать. Либо о том, как заставить работать вышеописанный метод, либо о лучшем методе достижения того же результата.

#ifndef class1_h
#define class1_h

#include <iostream>

namespace CMPLX
{
    class cmplx {
        public:
            double re;//real part
            double im;//imaginary part        
            cmplx();
            cmplx(double x, double y);
            friend std::ostream& operator<< (std::ostream& os, cmplx x){
                return os << x.re << "+i*(" << x.im << ")" << std::endl;
            }
    };

    extern const cmplx cmplx0;
    extern const cmplx cmplxi;
};
#endif
#ifndef class2_h
#define class2_h

#include "cmplx.h"

namespace CMPLX
{
    class meta {
        private:
            double value1;
            cmplx value2;
        public:
            meta();
            meta(int x, cmplx y);
            friend std::ostream& operator<< (std::ostream& os, meta x){
                return os << x.value1 << " " << x.value2 << std::endl;
            }
            meta operate();
    };

    extern const meta meta0;
};
#endif
#include "cmplx.h"

using namespace CMPLX;

const cmplx cmplxi = cmplx(0.0, 1.0);
const cmplx cmplx0 = cmplx(0.0, 0.0);

cmplx::cmplx(){
    this->re = 0;
    this->im = 1;
}

cmplx::cmplx(double x, double y){
    this->re = x;
    this->im = y;
}
#include "cmplx.h"
#include "meta.h"

using namespace CMPLX;

const meta meta0 = meta(0.0, cmplxi);

meta::meta(){
    this->value1 = 0.0;
    this->value2 = cmplx0;
}

meta::meta(int x, cmplx y){
    this->value1 = x;
    this->value2 = y;
}

meta meta::operate(){
    double temp = this->value1;
    this->value1 = this->value2.re;
    this->value2.re = this->value2.im;
    this->value2.im = temp;
}
#include "lib.h"
#include <iostream>

using namespace CMPLX;

int main(){
std::cout << cmplx0 << std::endl;
std::cout << cmplxi<< std::endl;
std::cout << meta0<< std::endl;
std::cout << meta(0.5, cmplxi).operate() << std::endl;

return 0;
}
#ifndef lib_h
#define lib_h

#include "cmplx.h"
#include "meta.h"

#endif
# Compiler and flags
CXX = g++
CXXFLAGS = -Wall -g -Iheaders

# Directories
SRC_DIR = sources
OBJ_DIR = obj
BIN_DIR = bin
XPL_DIR = examples

# Target name
TARGET = $(BIN_DIR)/lib.lib

# Find all source files in the SRC_DIR
SRCS = $(wildcard $(SRC_DIR)/*.cpp)

# Create a list of object files by replacing .cpp with .o
OBJS = $(patsubst $(SRC_DIR)/%.cpp, $(OBJ_DIR)/%.o, $(SRCS))

# Find all example files in the XPL_DIR
XPLS = $(wildcard $(XPL_DIR)/*.cpp)

# Create a list of executible files by replacing .cpp with .exe
EXES = $(patsubst $(XPL_DIR)/%.cpp, $(BIN_DIR)/%.exe, $(XPLS))

# Default target
all: library examples

examples: $(EXES)

library: $(TARGET)

$(BIN_DIR)/%.exe: $(XPL_DIR)/%.cpp
    if not exist $(BIN_DIR) mkdir $(BIN_DIR)
    $(CXX) $(CXXFLAGS) -o $@ $< $(BIN_DIR)/lib.lib

# Linking
$(TARGET): $(OBJS)
    if not exist $(BIN_DIR) mkdir $(BIN_DIR)
    ar rcs $@ $^

# Compilation
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
    if not exist $(OBJ_DIR) mkdir $(OBJ_DIR)
    $(CXX) $(CXXFLAGS) -c $< -o $@ 

# Clean up
clean:
    del $(OBJ_DIR) $(BIN_DIR)

.PHONY: all clean
Феликс
Вопрос задан18 июня 2024 г.

1 Ответ

Ваш ответ

Загрузить файл.