2015-07-21 85 views
-1

我有两个类BaseJob和DerivedJob,然后我与它的工作的一些代码:C++如何使用继承

Beanstalkpp::BaseJob* Beanstalkpp::Client::reserve() { 

    if (something) 
    { 
     return new ExtendedJob(some_data); 
    } 
    if (something_else) 
    { 
     return new SpecialJob(some_data); 
    } 
} 

我想用它喜欢:

ExtendedJob *j = client.reserve() 

但到目前为止,我越来越:

error: invalid conversion from ‘Beanstalkpp::BaseJob*’ to ‘Beanstalkpp::ExtendedJob*’ [-fpermissive] 

更新:

class BaseJob 
{ 
    ... 
} 

class ExtendedJob : public BaseJob 
{ 
    ... 
} 

更新2: 如此,因为很多答案说,这是不可能的,或者,如果是的话,做一些危险的,我想更多的描述我尝试解决。

我对工作的一些基本功能与类似工作:

BaseJob reserve() 
void del(BaseJob& j) 
void bury(BaseJob& j) 
... 

然后,我有一些工作clases像ExtendedJob,SpecialJob所有延伸BaseJob。上面提到的所有函数都会执行相同的操作(会调用对象的相同函数调用)。

所以我看到2种方式解决我的问题

  • 对于每个作业类型,我将创建一个像reserveBaseJob(),reserveSpecialJob()自定义函数的...
  • 对于每一个功能,我将创造同样的功能但作为模板,然后函数每次调用将包含类的名称,如:德尔()

所有作业类实现相同的接口....

+4

什么是继承层次?模板来自哪里? –

+0

@FredLarson对不起,我删除了模板并添加了层次结构 –

回答

0

这不是p因为你永远不能确定你的client.reserve()创建ExtendedJob,而不是SpecialJob或其他任何东西。考虑你的代码如何运行,如果reserve()创建SpecialJobSomeOtherUnrelatedJob,但你试图将它保存到指针ExtendedJob

如果你确信reserve()总是创建ExtendedJob或它的子类无论它是从调用,然后改变其声明返回ExtendedJob*

如果你确信reserve()总是创建ExtendedJob或它的子类时,它从特定的地方叫,然后你可以使用dynamic_cast,但无论如何这种味道不好的设计。

+0

所以基本上我所要做的就是创建像reserveExtendedJob(),reserverSpecialJob(),reserveSomeOtherJob()等功能吧? –

+1

@DusanPlavak,这个我不能说,因为这很大程度上取决于你的架构。无论如何,一堆这样的功能似乎并不合适。也许它会是一个模板化的功能,或者你会改变你的设计并完全避免它。 – Petr

0

这是因为您隐式地将基类类型转换为派生类类型。为此,使用dynamic_cast<T>

ExtendedJob *j = dynamic_cast<ExtendedJob*>(client.reserve()); 

这将产生NULL如果转换不能进行,例如,因为该指针是另一种类型的层次结构。

0

此错误的原因是该函数的返回类型是Beanstalkpp::BaseJob*。所以,当你返回ExtendedJob*时,它隐含地铸造成BaseJob*

然后,在您的程序代码中,您要从基指针向下倾向ExtendedJob*,这很危险,因为它也可以是SpecialJob*。如果您希望指针会ExtendedJob*,你可以尝试明确的转换非常谨慎:

ExtendedJob* j = dynamic_cast<Beanstalkpp::ExtendedJob*>(client.reserve()); 
if (NULL != j) { 
    // your code here 
} 
0

如果可能的话,我建议做这样的:

BaseJob* j = client.reserve(); 

,包括插入到BaseJob中一些由ExtendedJob覆盖的虚拟方法。

0

假设BaseJobExtendedJobSpecialJob基类,你应该做的:

BaseJob * j = client.reserve(); 

你得到的错误意味着你想BaseJob(的reserve()返回类型)转换为一个它的孩子。编译器无法确定这一点,所以会引发错误。一个dynamic_cast<ExtendedJob*>将强制这个转换,但它通常不是一个好设计。

0

派生到基类的转换是可能的。但是,这种转换,即派生到基类转换在您的代码中没有看到。你面临的问题是,你做的派生类点的指针,它的基类的位置:

ExtendedJob *j = client.reserve() 

的问题是,ExtendedJob将指向BaseJob对象的一部分(即ExtendedJob的成员) 。但是没有这样的成员,因此编译器会标记错误。

修复是使用的dynamic_cast

ExtendedJob *j = dynamic_cast<ExtendedJob*>(client.reserve())