在C ++中是否可以将父对象转换为子对象?

时间:2019-09-10 15:42:12

标签: c++

我是C ++的新手,正如标题所述,我正在尝试将父对象强制转换为其子对象之一。例如,我有一个Operation类,然后是Operation的几个子类(我们将它们称为OpAOpBOpC)。我想做这样的事情:

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对象。

2 个答案:

答案 0 :(得分:4)

  

在C ++中是否可以将父对象转换为子对象?

如果引用的对象是该派生类型的实例,则可以将引用或指向父对象的指针转换为引用或指向派生类。这称为向下转换。

有两种选择:

    如果您确定知道派生类型的对象,则可以使用
  • static_cast。如果不是,那么使用static_cast会导致未定义的行为,因此,除非可以证明它是正确的,否则不要使用它。
  • 即使您不确定实际的派生类型,也可以使用
  • dynamic_cast。如果对象原来不是适当的类型,则将导致空指针或引用异常。 dynamic_cast仅在对象是多态的(至少一个虚拟成员函数)时才能使用。

但是,向下转换通常不是一个好的解决方案,通常最好寻找另一种解决方案,以了解为什么您认为自己需要它。通常,正确的解决方案是虚函数。


  

想做这样的事情:

假设OperationOpAOpBOpC的基数,您可以精确地做到这一点(在示例中是这样)。请注意,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...