You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

派生类对象存入父类类型容器后,如何访问其成员函数?

Why Your Derived Class Information Is Lost and How to Fix It

The issue you're hitting is called object slicing—this is exactly what's happening when you store a B object into a container that holds A instances. Let me break this down and show you how to fix it.

What's Object Slicing?

Your AVector is built on top of a std::vector<A>, which stores actual A objects (not references or pointers). When you pass a B object to push_back, the compiler only copies the base class (A) portion of the B object into the vector. All the unique parts of B (like the sayHello() method) get "sliced off"—the vector element is now just a plain A, with no trace of B left. That's why you can't call sayHello() or cast it back to B* later.

How to Preserve Derived Class Information

To keep the full B object intact, you need to store pointers (or smart pointers) to A (and its derivatives) instead of storing the objects directly. Pointers don't get sliced—they just point to the full object in memory. Here's how to adjust your code:

Step 1: Update the Base Class with Virtual Functions

First, add a virtual destructor to A (critical for safely deleting derived objects via base pointers) and make sayHello() a virtual function so you can call it polymorphically:

#include <iostream>
#include <vector>
#include <memory> // For smart pointers

class A {
private:
    int id_;
public:
    A(int id);
    virtual ~A() = default; // Virtual destructor for safe cleanup
    int id() { return id_; }
    virtual std::string sayHello() const { return "From Base A"; } // Virtual method
};

A::A(int id) : id_{id} {}

class B : public A {
public:
    B(int id);
    std::string sayHello() const override { return "Hello"; } // Override base method
};

B::B(int id) : A(id) {}

Step 2: Modify AVector to Store Smart Pointers

Replace the underlying std::vector<A> with std::vector<std::unique_ptr<A>> (using unique_ptr is safer than raw pointers because it handles automatic cleanup):

class AVector : private std::vector<std::unique_ptr<A>> {
public:
    // Push a pre-made unique_ptr<A>
    void push_back(std::unique_ptr<A> obj) {
        std::vector<std::unique_ptr<A>>::push_back(std::move(obj));
    }

    // Helper to emplace a derived class directly (cleaner syntax)
    template<typename Derived>
    void emplace_back(int id) {
        std::vector<std::unique_ptr<A>>::emplace_back(std::make_unique<Derived>(id));
    }

    // Bring over the vector methods you need
    using std::vector<std::unique_ptr<A>>::size;
    using std::vector<std::unique_ptr<A>>::at;
    using std::vector<std::unique_ptr<A>>::begin;
    using std::vector<std::unique_ptr<A>>::end;
};

Step 3: Use the Container Correctly in Main

Now you can store A and B objects without slicing, and call their methods polymorphically:

int main() {
    AVector av;

    // Emplace A and B objects directly into the container
    av.emplace_back<A>(3);
    av.emplace_back<A>(8);
    av.emplace_back<B>(12);

    // Call sayHello() polymorphically via the base pointer
    std::cout << av.at(2)->sayHello() << std::endl; // Outputs "Hello"

    // If you need to cast to B* (to access B-specific methods not in A), use dynamic_cast
    if (B* b_ref = dynamic_cast<B*>(av.at(2).get())) {
        std::cout << "Casted to B successfully, id: " << b_ref->id() << std::endl;
    } else {
        std::cout << "Object at index 2 is not a B" << std::endl;
    }

    return 0;
}

Key Takeaways

  • Object slicing happens when you store a derived class object in a base class container—only the base part is kept.
  • Store smart pointers (like unique_ptr) to the base class to preserve the full derived object.
  • Use virtual functions to enable polymorphic calls (calling derived methods via base pointers).
  • dynamic_cast lets you safely convert a base pointer back to a derived pointer (it returns nullptr if the conversion isn't valid, so always check the result).

内容的提问来源于stack exchange,提问作者Michael Schäfer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:05:19