将Vehicle类用于Table模板类时出现「invalid abstract parameter type 'Vehicle'」错误的技术求助
首先,你遇到的invalid abstract parameter type 'Vehicle'错误,核心原因是Vehicle类实际上是一个抽象类,无法被实例化,而你的Table模板在addNewRecord方法里需要创建T的实例(new T(record)),抽象类不能被实例化,所以编译直接报错。
为什么Vehicle会变成抽象类?看你的代码就能发现关键的拼写错误:
- 基类
Storable中应该定义了纯虚函数virtual void setDataFrom(Storable*) = 0;(从Table.cpp里的record->setDataFrom(&updateRecord);调用可以推测) - 但你的Vehicle类里实现的是
void setDataForm (Storable * s);——注意函数名是setDataForm(结尾是m?不对,是From和Form的拼写差异!)
因为Vehicle没有正确实现基类的纯虚函数,所以它自动成为抽象类,无法被实例化,自然不能作为Table的模板参数。
修复步骤
1. 修正Vehicle类的函数名拼写
把Vehicle.h和Vehicle.cpp里的setDataForm全部改成setDataFrom,和基类的纯虚函数名保持一致:
- Vehicle.h中:
void setDataFrom(Storable * s);
- Vehicle.cpp中:
void Vehicle ::setDataFrom(Storable *s) { Vehicle *v = dynamic_cast<Vehicle *> (s); if(v) { this->registrationnumber= v->registrationnumber; this->type= v->type; this->companyname= v->companyname; this->seats= v->seats; this->pricePerKm = v->pricePerKm; this->PUCExpirationDate= v->PUCExpirationDate; } }
2. 修复Vehicle构造函数的变量赋值错误
在Vehicle.cpp的构造函数里,你写了:
this-> companyname = companyname;
这里的参数是companyName(大写N),但你用了companyname(小写n),这会导致成员变量被错误赋值(局部变量和成员变量同名,编译器优先取局部变量,但这里局部变量不存在,会触发编译警告/错误),修正为:
this->companyname = companyName;
3. 修正头文件包含问题
你现在在头文件里包含了.cpp文件(比如#include "storable.cpp"),这会导致代码重复定义,正确的做法是包含对应的头文件(比如#include "storable.h"),确保每个cpp文件只被编译一次。
4. 处理模板类的实现问题
C++模板的实现通常需要放在头文件中,或者在头文件末尾包含模板的cpp文件,否则链接器会找不到模板实例的定义。你可以把Table.cpp的内容全部移到Table.h里,或者在Table.h的末尾添加:
#include "Table.cpp"
5. 其他小问题修复
- Vehicle的
getVehicleTypeName函数里,case VehicleType:: towera:的空格去掉,改成case VehicleType::towera:; - 枚举
towera返回的是"Tower",如果是笔误可以改成对应的名称(比如"Towera"); - Table.cpp里的
throw new MemoryError();应该改成throw MemoryError();,不需要用new抛出异常。
验证修复
完成以上修改后,Vehicle类就不再是抽象类了,你可以正常将它作为Table的模板参数使用,比如Table<Vehicle> vehicleTable("vehicles.txt");,编译就不会再报抽象参数类型的错误了。
内容的提问来源于stack exchange,提问作者tanya yadav

