我正在尝试创建一个充当基础对象的类,然后将其细分(=实现)以用于各种目的。
我想定义一个或多个纯虚函数,因此无论如何都是基类的子类,并且不要忘记实现它们。
有一点需要注意,纯虚函数的签名包括基础对象的类型。一旦被分类,函数定义当然不再与基类定义匹配。 E.g:
class BaseItem
{
public:
virtual std::string getDifferences(const BaseItem& item) = 0;
}
所以,在我想做的派生类中:
class DerivedClass : public BaseItem
{
public:
virtual std::string getDifferences(const DerivedClass& item) = 0;
private:
std::string derivedItemCustomObject;
}
当然编译器不会接受。我当然可以使它成为BaseItem
,但是我不能在派生类中使用任何对象。
我是否必须使用施法才能完成此任务?
如果我的意图/问题不明确,请告诉我。
答案 0 :(得分:4)
无需更改功能签名。请看以下内容:
class BaseItem
{public:
virtual std::string getDifferences(const BaseItem& item) = 0;
};
class DerivedClass : public BaseItem
{public:
virtual std::string getDifferences(const BaseItem& item) // keep it as it's
{
const DerivedClass& derivedItem = static_cast<const DerivedClass&>(item);
}
};
可以毫不畏惧地使用static_cast<>
,因为DerivedClass::getDifferences()
仅针对DerivedClass
对象调用。为了说明,
BaseItem *p = new DerivedClass;
DerivedClass obj;
p->getDifferences(obj); // this always invoke DerivedClass::getDifferences
如果您担心某个时候最终可能会将任何其他派生类对象作为参数传递给该方法,那么请改用dynamic_cast<>
并在该转换失败时抛出异常。
答案 1 :(得分:2)
目前还不清楚你想要实现的目标。假设编译器允许您执行此操作(或者通过强制转换方式执行此操作),那么它将在类型系统中打开以下漏洞:
class BaseItem
{
public:
virtual std::string getDifferences(const BaseItem& item) = 0;
};
class DerivedClass : public BaseItem
{
public:
virtual std::string getDifferences(const DerivedClass& item)
{
item.f();
// ...
}
void f() const {}
};
class DerivedClass2 : public BaseItem
{
public:
virtual std::string getDifferences(const DerivedClass2& item) { ... }
};
void g()
{
BaseItem* x = new DerivedClass;
// oops, calls DerivedClass::f on an instance of DerivedClass2
x->getDifferences(DerivedClass2());
}
你的设计可能不对。
答案 2 :(得分:2)
我假设编译器接受但DerivedClass :: getDifferences不会覆盖BaseItem :: getDifferences。这是一种实现您显然想要的方式
template <typename T>
class DerivedHelper: public BaseItem {
public:
virtual std::string getDifferences(const BaseItem& item) {
getDifferences(dynamic_cast<const T&>(item));
}
virtual std::string getDifferences(const T& item) = 0;
};
class DerivedClass : public DerivedHelper<DerivedClass>
{
public:
// not more needed but providing it will hide getDifferences(const BaseItem& item)
// helping to statically catch some cases where a bad argument type is used.
virtual std::string getDifferences(const DerivedClass& item) = 0;
private:
std::string derivedItemCustomObject;
};
但请注意,如果参数不是正确的类,则会有一个运行时检查会抛出异常。
答案 3 :(得分:1)
实现此目的的一种方法是使用模板并使参数成为派生类型的类型
template <typename T>
class BaseItem {
public:
virtual std::string getDifferences(const T& item) = 0;
};
class DerivedClass : public BaseItem<DerivedClass> {
public:
virtual std::string getDifferences(const DerivedClass& item) {
// Implement it here
}
};
答案 4 :(得分:0)
如果给定的BaseItem是DerivedClass实例,则应该使用从BaseItem转换为DerivedClass +运行时检查。