The structure of the code is as follows:
- root
- |----ssa
- |----|----node
- |----|----|----read.hpp
- |----|----|----read.cpp
- |----big
- |----|----node
- |----|----|----derived.hpp
- |----base
- |----|----node
- |----|----|----base.hpp
- |----|----|----base.cpp
In base.hpp:
namespace big::node{ //forward declaration
template <typename ValueType_, typename Stack_>
class Derived;
}
namespace base::node{
template <typename ItemType>
class Base {
public:
explicit Base(int id) : id_(id) {};
Base(const Base<ItemType>& w); //Implementation is in base.cpp
int getId() const; //Implementation is in base.cpp
virtual ~Base() {}
private:
int id_;
}
}
In base.cpp:
#include <base/node/base.hpp>
#include <big/node/derived.hpp>
namespace base::node{
template <typename ItemType>
int Base<ItemType>::getId() const {
return id_;
}
template <typename ItemType>
Base<ItemType>::Base(const Base<ItemType>& b) {
this->id_ = b.getId();
*this = (Base<ItemType>&)(dynamic_cast<big::node::Derived<ItemType, tlx::FunctionStack<ItemType>>&>(b)); // we have to downcast then upcast to maintain the member in derived class
}
}
In derived.hpp:
namespace big::node {
template <typename ValueType_, typename Stack_ = tlx::FunctionStack<ValueType_>>
class Derived : public base::node::Base<ValueType_> {
Derived() = default;
explicit Derived(int id) : base::node::Base<ValueType_>(id) {};
Derived(base::node::Base<ValueType>& b) : base::node::Base<ValueType>(b.getId()), id_(b.getId()) {}
}
}
read.cpp in ssa call the function getId() of base class. If implementation of getId() is written in base.hpp, build and link will be fine. But since the derived class and the base class include each other, we have to create the base.cpp to include base.hpp and derived.hpp, and forward declaration of the derived class is also in base.hpp.
Build is successful. But when generate the executable of main, the error shows "undefined reference to xxxx", which xxx is the function that calls getId or copy constructor of the base class.
In CMakeLists.txt of ssa:
set(DEFINITIONS "")
set(INCLUDE_DIRS ${INCLUDE_DIRS})
file(GLOB SQL_SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/node/*.cpp
......)
add_library(ssa STATIC ${SQL_SRCS})
target_compile_definitions(ssa PUBLIC ${DEFINITIONS})
target_include_directories(ssa SYSTEM PUBLIC ${INCLUDE_DIRS})
target_link_libraries(ssa)
add_executable(main test/main.cpp)
target_compile_definitions(main PUBLIC ${DEFINITIONS})
target_link_libraries(main ssa base big)
In CMakeLists.txt of base:
set(INCLUDE_DIRS ${INCLUDE_DIRS})
set(LINK_LIBRARIES ${LINK_LIBRARIES})
file(GLOB BASE_SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/node/*.cpp
......)
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../)
add_library(base STATIC ${BASE_SRCS})
target_compile_definitions(base PUBLIC)
target_include_directories(base SYSTEM PUBLIC ${PROJECT_SOURCE_DIR} ${INCLUDE_DIRS})
target_link_libraries(base ${LINK_LIBRARIES})
In CMakeLists.txt of big:
set(INCLUDE_DIRS ${INCLUDE_DIRS})
set(LINK_LIBRARIES ${LINK_LIBRARIES})
file(GLOB BIG_SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/node/*.[ch]pp
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../)
add_library(big STATIC ${BIG_SRCS})
target_compile_definitions(big PUBLIC ${BIG_DEFINITIONS})
target_include_directories(big PUBLIC ${PROJECT_SOURCE_DIR})
target_include_directories(big SYSTEM PUBLIC ${PROJECT_SOURCE_DIR} ${INCLUDE_DIRS})
target_link_libraries(big ${BIG_LINK_LIBRARIES})
Since the project is slightly complicated, the above code is not complete. What the reason for undefined reference error ?