簡體   English   中英

在向量C ++中從超類調用子類方法

[英]Calling subclass methods from superclass in a vector C++

我試圖將多個子類元素添加到向量中,並通過它們迭代調用覆蓋方法,並希望它在可能的情況下調用覆蓋方法。 但是我發現它似乎只在調用超類方法。

我學習了Java,但不確定為什么要用C ++做到這一點。 我嘗試使用超類的指針向量重寫代碼,並將子類的指針轉換為超類。 然后通過指針訪問它。

理想情況下,我不想在矢量中放置一個指針列表,因為那樣的話我就必須手動刪除每個指針(我相信嗎?)以防止內存泄漏,因為我將使用new創建對象,因此它們會通過方法調用而持久存在將它們添加到向量中。

有沒有更好的方法可以做到這一點?還是在不需要父類時堅持使用指針並在創建的對象上調用delete? 向量最好是X類的列表,而不是X類的指針的列表

我的結構是:

class a { vector vec of class X,
    method to create and add an instance of X into vector vec,
    method to create and add an instance of Y into vector vec }
class X { talk() }
class Y : public X { talk() }

代碼演示了我理想的操作,但是僅通過調用超類方法來顯示其損壞:

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <vector>

class A {
  public:
    virtual void talk() { printf("A\n"); }
};

class B: public A {
  public:
      void talk() { printf("B\n"); }
};

int main(void) {
    std::vector<A> vec;
    std::vector<A*> vec2;
    A a;
    B b;
    a.talk();
    b.talk();

    vec.push_back(a);
    vec.push_back(b);
    vec2.push_back(&a);
    vec2.push_back(&b);

    for(int i = 0; i < vec.size(); i++) {
        vec[i].talk();
        vec2[i]->talk(); //bad but short for example
    }

}

要獲得多態行為,您需要將virtual說明符添加到要在派生類中重寫的基類中的函數。

class A {
public:
    virtual void talk() { printf("A\n"); }
};

您還應該養成在派生類中的重寫函數上添加override說明符的習慣,以便編譯器可以幫助您解決此類問題。

class B: public A {
public:
    virtual void talk() override { printf("B\n"); }
//                      ^ Compiler will report an error if base class' function
//                        is not virtual.
};

同樣,您不能將派生對象分配給基類的實例,否則將發生切片

std::vector<A> vec;
/* ... */
B b;
/* ... */
vec.push_back(b); // Slicing. Information only in B is lost.

使用virtual說明符的實時示例

沒有virtual說明符的實時示例

您應該將方法聲明為virtual方法,以便能夠在子類中覆蓋它們。 將析構函數虛擬化也是一個好習慣。

class A {
public:
   virtual void talk() { printf("A\n"); }
   virtual ~A(){}
};

class B: public A {
public:
   // using virtual is not really necessary here, but it's good for clarity.
   virtual void talk() { printf("B\n"); }
};

該方法應該是虛擬的
在java中,默認情況下方法是虛擬的。

class A {
  public:
    virtual void talk() { printf("A\n"); }
};

class B: public A {
  public:
      virtual void talk() override { printf("B\n"); } //override key word is in C++  0x and above
};

我認為您缺少的是方法聲明中的virtual關鍵字。 如果要在調用父類中的方法時使用子類方法,則必須將這些方法聲明為virtual

如果不使用指針,則在將對象復制到向量中時會得到“對象切片”。 這會將對象減少為矢量模板參數中聲明的基本類型。 因此沒有子類,因此沒有子類方法可以調用,即使該方法是虛擬的也是如此。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM