如何编译仅在头文件中的C++接口

How to compile a C++ interface that's in a header file only

本文关键字:文件 接口 C++ 何编译 编译      更新时间:2023-10-16

我有一个类Event和一个子类ServerEvent,但是Event类只是ServerEvent扩展/继承的接口。当我运行make时,没有生成Event.o,并且我得到一个不存在的错误。

编译这个接口的正确方法是什么?在makefile中添加什么?另外,我有一个受保护的构造函数的原因是,Event不能被实例化。我不能使用虚拟构造函数——继承的正常方式是什么?

编辑:包括makefile,ServerEvent.cpp和编译错误现在

Event.h

#ifndef EVENT_H
#define EVENT_H
#include <string>
#define EVENT_STOP 0
#define EVENT_START 1
class Event {
private:
protected:
    double time;
    std::string label;
    int type; // EVENT_START OR EVENT_STOP
    Event();
public:
};
#endif

ServerEvent.h

#ifndef SERVEREVENT_H
#define SERVEREVENT_H
#include "Event.h"
#include <vector>
class ServerEvent: public Event {
private:
public: 
    ServerEvent(std::vector<std::string> tokens);
};
#endif

服务器事件.cpp

#include "Event.h"
#include "ServerEvent.h"
#include <cstdlib>
#include <sstream>
ServerEvent::ServerEvent(std::vector<std::string> tokens) {
    std::stringstream stream(tokens[0]);
    stream >> time;
}

生成文件

OBJ = correngine.o CSVManager.o CorrelationEngineManager.o ServerEvent.o
CC = g++
CFLAGS = -c -Wall -pedantic
LFLAGS = -Wall -pedantic
EXE =   correngine 
correngine : $(OBJ) 
    $(CC) $(LFLAGS) $(OBJ) -o $(EXE)
correngine.o : correngine.cpp correngine.h CSVManager.h
    $(CC) $(CFLAGS) correngine.cpp
CSVManager.o : CSVManager.cpp CSVManager.h
    $(CC) $(CFLAGS) CSVManager.cpp
CorrelationEngineManager.o : CorrelationEngineManager.cpp CorrelationEngineManager.h Event.o
    $(CC) $(CFLAGS) CorrelationEngineManager.cpp
Event.o : Event.h
    $(CC) $(CFLAGS) Event.h
ServerEvent.o: ServerEvent.cpp ServerEvent.h Event.h
    $(CC) $(CFLAGS) ServerEvent.cpp 
clean : 
    rm *.o $(EXE)

编译错误

ServerEvent.o: In function `ServerEvent::ServerEvent(std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >)':
ServerEvent.cpp:(.text+0x11): undefined reference to `Event::Event()'
ServerEvent.o: In function `ServerEvent::ServerEvent(std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >)':
ServerEvent.cpp:(.text+0xe1): undefined reference to `Event::Event()'
collect2: ld returned 1 exit status
make: *** [correngine] Error 1
  1. 这是一个具体的基类,它有数据成员,所以它不是一个"接口"。"接口"类指的是没有数据成员的类,所有成员函数在某种意义上都是纯虚拟的
  2. 您#将.h包含在.cpp文件中并编译该.cpp文件(但我不明白为什么要这样做,您必须#将"Event.h"包含在ServerEvent.cpp中,对吗?)
  3. 通常,要使接口类不可继承但不可实例化,就需要使用纯虚拟dtor,例如virtual~Event()=0;但是,由于我的观点0,这不适用于您的情况。受保护的ctor可能是您的案例的正确方式,但我不得不说,它看起来不像是一个优雅(或正确)的设计

无法实例化仅具有protectedprivate构造函数的类

当然,如果您编写实现(EDIT:如果您只有头文件,就没有编译头文件这回事),您就无法获得Event的实例,因为它是抽象,因为它只有protectedprivate构造函数。

要实例化一个实例,请编写一个从Event派生的类,该类具有公共构造函数,并且没有任何纯虚拟函数。

(你到底为什么要实例化抽象类?如果你需要实例化它,不要把它定义为摘要。)

构造函数不能是虚拟的,因为虚拟函数是根据与类(包括派生类)关联的指针表调用的。调用构造函数时,实例尚未构造,并且不能调用任何虚拟函数但是派生类的构造函数将隐式调用其基类的构造函数

据我所知,您不需要构造函数。您需要一个虚拟析构函数,并且需要实现的任何方法都必须等于0和virtual。

看这里:如何在C++中声明接口?