我是C ++的新手,正如标题所述,我正在尝试将父对象强制转换为其子对象之一。例如,我有一个Operation类,然后是Operation的几个子类(我们将它们称为OpA
,OpB
,OpC
)。我想做这样的事情:
Operation* op;
switch(someCondition)
{
case 0:
op = new OpA;
break;
case 1:
op = new OpB;
break;
case 2:
op = new OpC;
break
}
(希望这很有道理)。这在C ++中可能吗?我最熟悉Swift,它有一个非常简单的ObjectA as ObjectB
强制转换运算符,如果可以进一步阐明我要做什么的话。
谢谢!
编辑:我的措辞完全不好,哈哈。目前,我的代码如下所示:
Operation* op;
op = new OpA(parameter);
op->functionOfOpA();
我收到一个错误消息,即Operation类没有名为functionOfOpA()的成员,这是正确的。如果这能按我期望的那样工作,那么op现在将指向一个具有functionOfOpA()的OpA对象。
答案 0 :(得分:4)
在C ++中是否可以将父对象转换为子对象?
如果引用的对象是该派生类型的实例,则可以将引用或指向父对象的指针转换为引用或指向派生类。这称为向下转换。
有两种选择:
static_cast
。如果不是,那么使用static_cast
会导致未定义的行为,因此,除非可以证明它是正确的,否则不要使用它。dynamic_cast
。如果对象原来不是适当的类型,则将导致空指针或引用异常。 dynamic_cast
仅在对象是多态的(至少一个虚拟成员函数)时才能使用。但是,向下转换通常不是一个好的解决方案,通常最好寻找另一种解决方案,以了解为什么您认为自己需要它。通常,正确的解决方案是虚函数。
想做这样的事情:
假设Operation
是OpA
,OpB
和OpC
的基数,您可以精确地做到这一点(在示例中是这样)。请注意,Operation
的析构函数应该是虚拟的,否则delete op
将具有不确定的行为。
请注意,您的示例中不涉及向下转换。您正在将指针转换为派生为基础的指针。这种转换是隐式的,称为向上转换,并且始终是安全的。
答案 1 :(得分:1)
当您的 actual 问题已经是answered时,请考虑一个完全不需要下垂的设计:
class Operation
{
public:
virtual ~Operation() { } // as mentioned already:
// you should add a virtual destructor
virtual void functionOfOperation() = 0; // having a general name...
};
通过提供虚函数,您可以允许派生类重写基类中的函数,即。 e。根据自己的需要修改功能的行为。在上面的示例中,该函数是纯虚函数,即。 e。没有提供实现,无论如何这可能都没有意义。这使类成为抽象。 e。您不能创建纯Operation
类的实例,而只能创建派生类型。这些需要覆盖纯虚函数,否则它们也保持抽象。
class OpA
{
public:
void functionOfOperation() override
{
// appropriate implementation
}
};
override
不是强制性的,但是对于基类和派生类中的签名不匹配(由于基类的版本后来更改或仅由于无人照管而导致的错误)检测错误非常有用,所以这是个好习惯。
Operation* op = new OpA();
op->functionOfOperation(); // will call OpA's variant
说明虚拟功能和非虚拟功能之间的区别:
class Base
{
public:
virtual ~Base() { }
void normalFunction()
{ std::cout << "normal (base)" << std::endl; }
virtual void virtualFunction()
{ std::cout << "virtual (base)" << std::endl; }
};
class Derived : public Base
{
public:
void normalFunction()
{ std::cout << "normal (derived)" << std::endl; }
void virtualFunction() override
{ std::cout << "virtual (derived)" << std::endl; }
};
请注意,您不能将override
关键字应用于非虚函数!非虚拟函数不会覆盖基类的函数,它们只会隐藏它们:
Derived* derived = new Derived();
Base* base = derived;
base->normalFunction(); // outputs "normal (base)"
base->virtualFunction(); // outputs "virtual (derived)" (!)
derived->normalFunction(); // outputs "normal (derived)"
delete base; // due to virtual destructor, we can use either base or derived...