【问题标题】:Parent object call Child method C++父对象调用子方法 C++
【发布时间】:2015-06-18 13:43:36
【问题描述】:

我在 C++ 中的继承有一些困难。假设我有一个类基父:

class Parent{
public:
      ...
      virtual Parent Intersection(Parent anotherParent);

}

还有 2 个子类 Numeric 和 Symbolic,实现方法 Intersection:

class Numeric : public Parent{
public:
      ...
      Numeric Intersection(Numeric anotherNumeric)
      {
       ...
      }; // do intersection with another object numeric

}

// class Symbolic
class Symbolic : public Parent{
public:
      ...
      symbolic Intersection(Symbolic anotherSymbolic)
      {
       ...
      }; // do intersection with another object symbolic

}

最后一个类ParentVector:

class ParentVector : public Parent{
public:
      ...
      ParentVector Intersection(ParentVector anotherParentVector);

private:
      std::vector<Parent> vtParent; // vector stock object Parent (Numeric or Symbolic)

}

我想要矢量 vtParent 存储 2 种类型的对象:数字或符号。所以我创建了一个父对象的向量。

问题是:我想得到 2 个向量 ParentVector 的交集。

我可以在向量 vtParent 中添加一个对象 Numeric 或 Symbolic 但我不能调用方法 Intersection 对应于每种类型的对象。它总是调用类Parent的方法Intersection。

有人有什么想法或建议吗?非常感谢。

//edit : 我忘记了 ParentVector 类也是 Parent 类的子类。

// 更新:感谢您提供的所有有用帮助。现在,我想执行下面的代码来计算 2 个向量 Parent 的交集:

ParentVector* Intersection(ParentVector anotherParentVector){
     ParentVector* result;
     Parent* tmp;

     for( int i = 0; i < this->vtParent.size(i); i++ ){
           // PROBLEM with this line because I don't write the code of 
           // function 'virtual Parent* Parent::Intersection(Parent anotherParent)'

          *tmp = this->vtParent.at(i)->Intersection(anotherParentVector.getParentVector().at(i));
          result->getParentVector.push_back(tmp);
     }
}

我没有写函数'virtual Parent* Parent::Intersection(Parent anotherParent)'的代码,所以我不能执行上面的代码。有人知道如何解决这个问题?

// 这里的想法是我想调用函数'Numeric* Intersection(Numeric anotherNumeric)' 或'Symbolic* Intersection(Symbolic anotherSymbolic)'

// FINISH,谢谢大家的建议。

【问题讨论】:

  • 你有不同返回类型的虚函数。见this

标签: c++ inheritance


【解决方案1】:

您的子类正在更改 Intersection 函数的返回类型和参数类型,这实质上使它成为一个新函数,而不是一个行为多态的函数。函数必须具有相同的函数签名。

【讨论】:

  • 你的意思是如果我改变函数的返回类型:Numeric Intersection(Numeric anotherNumeric) to Parent Intersection(Parent anotherNumeric) ???
【解决方案2】:

您的代码中有 3 个问题:

在 STL 容器中存储值时,将调用复制构造函数,子类对象将被切片。所以如果你想保持某个对象的多态性,可以使用指针/智能指针或引用。容器场景下,pointer/smart_pointer比较合适。

std::vector<Parent*> vtParent

基类和派生类的参数类型必须相同。

返回类型问题见enter link description here

class Parent{

public:

  ...
  virtual Parent& Intersection(Parent anotherParent);

}


class Symbolic : public Parent{
public:
      ...
      symbolic& Intersection(Symbolic anotherSymbolic)
      {
       ...
      }; // do intersection with another object symbolic

}

【讨论】:

    【解决方案3】:

    如果您不使用 C++11,当您将符号或数字对象 push_back 放入向量中时,您将面临对象切片。如果 C++11 系统将使用移动语义来填充向量,如果您的类定义适用于它,您应该定义移动构造函数和移动赋值运算符,或者取决于这些函数的默认值。

    要克服对象切片,您可以使用

    std::vector<Parent*> vtParent;  
    

    代替使用std::vector&lt;Parent&gt; vtParent;

    并且虚函数应该保持与 Ami Tavory 和 Adam Finley 所观察到的相同的函数返回。但在您的情况下,您可以按如下方式使用,因为您的返回类型是协变的。

    virtual Parent* Intersection(Parent anotherParent);
    symbolic* Intersection(Symbolic anotherSymbolic);
    Numeric* Intersection(Numeric anotherNumeric);
    

    请注意,您的基类中缺少虚拟析构函数。

    编辑: 您可以按如下方式简化您的ParentVector::Intersection()

    std::vector<Parent*> Intersection(ParentVector anotherParentVector){
         std::vector<Parent*> result;
         Parent * tmp;
         std::vector<Parent*>::iterator it= vtParent.begin();
         for( ; it != vtParent.end(); ++it){
               tmp=    it->Intersection(anotherParentVector.getParentVector().at(i));
              result->getParentVector.push_back(tmp);
         }
         return result;
    }
    

    【讨论】:

    • 我不明白的是“虚拟函数应该保持相同的函数返回”。你能解释一下吗?
    • 感谢您的建议,您可以查看我的最新更新吗?
    • 谢谢你,Steephen,这与你说的不完全一样,但我用你的建议解决了我的问题。
    【解决方案4】:

    是的,这并不要求删除事物,只是为了向您展示您需要采取的路线

    #include <iostream>
    #include <vector>
    #include <memory>
    class Parent{
    public:
        virtual Parent* Intersection() = 0;
    };
    
    class Numeric : public Parent{
    public:
        Parent* Intersection()
        {
            std::cout << "\nNumeric!";
            return new Numeric;
        } // do intersection with another object numeric
    
    };
    
    // class Symbolic
    class Symbolic : public Parent{
    public:
        Parent* Intersection()
        {
            std::cout << "\nSymbolic!";
            return new Symbolic;
        } // do intersection with another object symbolic
    
    };
    
    class ParentVector{
    public:
        ParentVector()
        {
            vtParent.push_back(std::make_unique<Symbolic>());
            vtParent.push_back(std::make_unique<Numeric>());
        }
        void print()
        {
            for (const auto& e : vtParent) {
                e->Intersection();
            }
        }
        ParentVector Intersection(ParentVector anotherParentVector);
    
    private:
        std::vector<std::unique_ptr<Parent>> vtParent; // vector stock object Parent (Numeric or Symbolic)
    
    };
    
    
    int main()
    {
        ParentVector pvec;
        pvec.print();
    
        std::cout << '\n';
        system("PAUSE");
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 2018-04-09
      • 2015-10-11
      • 1970-01-01
      • 2012-07-13
      • 1970-01-01
      • 1970-01-01
      • 2016-02-14
      • 1970-01-01
      相关资源
      最近更新 更多