【问题标题】:Access derived virtual function from base class, good practice?从基类访问派生的虚函数,好的做法?
【发布时间】:2020-12-20 15:29:25
【问题描述】:

从它的基类中访问派生的虚函数有什么好的做法吗? 到目前为止,这是我得到的:

class A {
public:
    enum class AType{A,B,C,D};   
    AType aType = AType::A;    
    virtual void Do(){}
};

class B : public A {
public:  
    int val = 0;  
    B(int i) {
        aType = AType::B;
        val = i;
    }   
    void Do(){
        std::cout << val << std::endl;
    }
};

int main(){
    std::map<std::string, A> bunch;  
    bunch["01"] = B(10);
    bunch["02"] = B(15);
    bunch["03"] = B(80);

    for (auto& [k, b] : bunch){
        switch (b.aType){
        case A::AType::A:
            break;
        case A::AType::B:
            static_cast<B&>(b).Do();
            break;
        }
    }
}

我对在那里使用开关不太满意,任何建议都将不胜感激!

【问题讨论】:

  • As 的地图无法容纳Bs,请阅读对象切片。一旦你解决了这个问题,你为什么需要开关?你不能直接打电话给b.Do() 吗?
  • 为什么不直接调用虚拟方法 Do() 而不管类型如何?还是我错过了什么?
  • 好吧,映射是A类型的,当我对A中的B调用do时,它调用的是A的虚函数而不是B的派生函数。我不知道切片,我正在阅读,希望我做对了

标签: c++ inheritance virtual


【解决方案1】:

您应该分配一个指针或引用以在 C++ 中使用多态性。如果您将子类分配为值,则会有对象切片。我会使用std::unique_ptr 而不是像下面这样的原始指针,它会打印出10 15 80 作为例外。

#include <memory>
#include <map>

class A {
public:
    enum class AType { A, B, C, D };
    AType aType = AType::A;
    virtual void Do() {}
};

class B : public A {
public:
    int val = 0;
    B(int i) {
        aType = AType::B;
        val = i;
    }
    void Do() override {
        std::cout << val << std::endl;
    }
};

int main() {
    std::map<std::string, std::unique_ptr<A>> bunch;
    bunch["01"] = std::make_unique<B>(10);
    bunch["02"] = std::make_unique<B>(15);
    bunch["03"] = std::make_unique<B>(80);

    for (auto& [k, b] : bunch) {
        b->Do();
    }

    return 0;
}

【讨论】:

  • @drescherjm,对,不再需要它。很好的指出。
  • 非常感谢!我从未使用过唯一的ptr,如果将B从地图中删除,它会自行删除吗?我也不再需要枚举了,太好了!
  • 是的,智能指针将在需要时处理对象的释放。是的,您很可能不需要枚举。
【解决方案2】:

首先,显示的不是我所说的“从基类调用”。否则, 从基类方法调用派生虚方法是使用虚函数的主要原因之一。另一个原因是通过指向基类的指针调用方法,就像您打算做的那样。

另外,如上所述,在:

bunch["01"] = B(10);

B 类型的临时对象被静默地转换(切片)为 A 类的对象。您或许应该使用指向 A 的指针映射。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-24
    相关资源
    最近更新 更多