0

I have a problem instantiating a generic object belonging to generic subclass. I get an undefined symbol error even though I implemented the function. I tried to recreate a minimal and reproducible example. The example I managed to recreate is similar to the one I got but here I get that the constructor is undefined while in my real but "un-pastable" code the error said that all the functions belonging to the superclass were undefined. But I think that the cause of the errors is the same and solving one will solve the other.

Here is the folder structure:

.
├── Makefile
├── abstract.cpp
├── concrete.cpp
├── interface.hpp
└── test
    ├── Makefile
    └── test.cpp

And here is the content of the files:

interface.hpp contains the classes definitions

#ifndef INTERFACE_123
#define INTERFACE_123
namespace ca {
template <typename T>
class AbstractClass {
 public:
  virtual ~AbstractClass() = default;

  virtual void simulate(unsigned n);

 protected:
  AbstractClass(int n);
  int n;
};
namespace seq {
template <typename T>
class ConcreteClass : public AbstractClass<T> {
 public:
  ConcreteClass(int n);
};
}  // namespace seq
}  // namespace ca

#endif

abstract.cpp and concrete.cpp contain the implementations. concrete.cpp basically only extends abstract.

abstract.cpp

#include <iostream>

#include "interface.hpp"
template <typename T>
ca::AbstractClass<T>::AbstractClass(int n) : n(n){};

template <typename T>
void ca::AbstractClass<T>::simulate(unsigned n) {
  std::cout << "inside simulate" << std::endl;
}

concrete.cpp

#include "interface.hpp"

template<typename T>
ca::seq::ConcreteClass<T>::ConcreteClass(int n) : AbstractClass<T>(n) {}

I build a static library with ar and ranlib and then try to use it in tests/test.

Here are the test/Makefile and test/test.cpp:

Makefile

CXX                     = g++
CXXFLAGS        = -std=c++17 -g -O3 -Wall -pedantic

.PHONY: all
all: libr test

test: test.o ../libminimalexample.a
        $(CXX) $(CXXFLAGS) -L.. -o $@ $< -lminimalexample
libr:
        cd .. && $(MAKE)
#include "../interface.hpp"

int main() {
  auto c = ca::seq::ConcreteClass<short>(10);
}

As it can be seen the test.cpp simply tries to create a ConcreteClass object. But when I go to compile the file I get the following error message:

g++ -std=c++17 -g -O3 -Wall -pedantic -L.. -o test test.o -lminimalexample Undefined symbols for architecture x86_64: "ca::seq::ConcreteClass::ConcreteClass(int)", referenced from: _main in test.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation)

But as it can be seen I did define the constructor of ConcreteClass in the file concrete.cpp, didn't I?

ninazzo
  • 427
  • 1
  • 4
  • 13

0 Answers0